creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/EnglishAuction.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n// adjusted, original copied from https://solidity-by-example.org/app/english-auction/\n\ninterface IERC721 {\n    function safeTransferFrom(address from, address to, uint tokenId) external;\n\n    function transferFrom(address, address, uint) external;\n}\n\ninterface IERC20 {\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    function transfer(address recipient, uint256 amount) external returns (bool);\n}\n\ncontract EnglishAuction {\n    event Start();\n    event Bid(address indexed sender, uint amount);\n    event Withdraw(address indexed bidder, uint amount);\n    event WithdrawFailed(address indexed bidder, uint amount);\n    event End(address winner, uint amount);\n\n    IERC721 public nft;\n    uint public nftId;\n\n    IERC20 public biddingToken;\n\n    address public seller;\n    address public beneficiary10Percent;\n    address public beneficiary90Percent;\n    uint public endAt;\n    bool public started;\n    bool public ended;\n\n    address public highestBidder;\n    uint public highestBid;\n    mapping(address => uint) public failedWithdraws;\n\n    constructor(address _nft, uint _nftId, uint _startingBid, address _biddingToken, address _beneficiary90Percent, address _beneficiary10Percent) {\n        nft = IERC721(_nft);\n        nftId = _nftId;\n\n        biddingToken = IERC20(_biddingToken);\n\n        seller = msg.sender;\n        beneficiary90Percent = _beneficiary90Percent;\n        beneficiary10Percent = _beneficiary10Percent;\n        highestBid = _startingBid;\n    }\n\n    function start() external {\n        require(!started, \"started\");\n        require(msg.sender == seller, \"not seller\");\n\n        nft.transferFrom(msg.sender, address(this), nftId);\n        started = true;\n        endAt = block.timestamp + 4 days + 11 hours;\n\n        emit Start();\n    }\n\n    function bid(uint bidAmount) external {\n        require(started, \"not started\");\n        require(block.timestamp < endAt, \"ended\");\n        require(bidAmount > highestBid, \"bidAmount < highest\");\n\n        require(biddingToken.transferFrom(msg.sender, address(this), bidAmount), \"transfer failed\");\n\n        // adjusted with logic that was previously in withdraw to automatically payout overbid accounts\n        if (highestBidder != address(0)) {\n            bool sent = biddingToken.transfer(highestBidder, highestBid); // we want to handle failures manually, failing payout shouldn't prevent bidding\n\n            if (sent) {\n                emit Withdraw(highestBidder, highestBid);\n            } else {\n                failedWithdraws[highestBidder] += highestBid;\n                emit WithdrawFailed(highestBidder, highestBid);\n            }\n        }\n\n        highestBidder = msg.sender;\n        highestBid = bidAmount;\n\n        emit Bid(msg.sender, bidAmount);\n    }\n\n    function withdrawFailed() external {\n        uint bal = failedWithdraws[msg.sender];\n        failedWithdraws[msg.sender] = 0;\n        require(biddingToken.transfer(msg.sender, bal), \"transfer failed\"); // we want to revert on failures\n\n        emit Withdraw(msg.sender, bal);\n    }\n\n    function end() external {\n        require(started, \"not started\");\n        require(block.timestamp >= endAt, \"not ended\");\n        require(!ended, \"ended\");\n\n        ended = true;\n        if (highestBidder != address(0)) {\n            nft.safeTransferFrom(address(this), highestBidder, nftId);\n\n            uint highestBid10Percent = (highestBid * 10) / 100;\n            require(biddingToken.transfer(beneficiary10Percent, highestBid10Percent), \"transfer failed\");\n            require(biddingToken.transfer(beneficiary90Percent, highestBid - highestBid10Percent), \"transfer failed\");\n        } else {\n            nft.safeTransferFrom(address(this), seller, nftId);\n        }\n\n        emit End(highestBidder, highestBid);\n    }\n\n    function setEndAt(uint newEndAtTimestamp) external {\n        require(msg.sender == seller, \"not seller\");\n        require(started, \"not started\");\n        require(!ended, \"ended\");\n        require(newEndAtTimestamp > block.timestamp, \"end at has to be in the future\");\n        endAt = newEndAtTimestamp;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": false,
        "runs": 1000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}