Transaction Hash:
Block:
16215077 at Dec-19-2022 12:12:11 AM +UTC
Transaction Fee:
0.000644628766125024 ETH
$1.46
Gas Used:
51,231 Gas / 12.582787104 Gwei
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x44092046...DBc039456 | (Prometheans: Deployer) |
0.260332068815710125 Eth
Nonce: 33
|
0.259687440049585101 Eth
Nonce: 34
| 0.000644628766125024 | |
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 117.445377225183380376 Eth | 117.445479687183380376 Eth | 0.000102462 | |
0xDaB66b4c...47635ECf8 |
Execution Trace
Proxy.fdd198c3( )

-
JollySwap.setRandomness( randomness=96563109460535109062060297287341467736967471803462889339984880090995856282807 )
setRandomness[JollySwap (ln:94)]
owner[JollySwap (ln:95)]
_getAddress[JollySwap (ln:60)]
_getSlotValue[JollySwap (ln:240)]
File 1 of 2: Proxy
File 2 of 2: JollySwap
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; /// @dev Proxy for NFT Factory contract Proxy { // Storage for this proxy bytes32 private constant IMPLEMENTATION_SLOT = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); bytes32 private constant ADMIN_SLOT = bytes32(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103); constructor(address impl) { require(impl != address(0)); _setSlotValue(IMPLEMENTATION_SLOT, bytes32(uint256(uint160(impl)))); _setSlotValue(ADMIN_SLOT, bytes32(uint256(uint160(msg.sender)))); } function setImplementation(address newImpl) public { require(msg.sender == _getAddress(ADMIN_SLOT)); _setSlotValue(IMPLEMENTATION_SLOT, bytes32(uint256(uint160(newImpl)))); } function setAdmin(address newAdmin) public { require(msg.sender == _getAddress(ADMIN_SLOT)); _setSlotValue(ADMIN_SLOT, bytes32(uint256(uint160(newAdmin)))); } function implementation() public view returns (address impl) { impl = address(uint160(uint256(_getSlotValue(IMPLEMENTATION_SLOT)))); } function _getAddress(bytes32 key) internal view returns (address add) { add = address(uint160(uint256(_getSlotValue(key)))); } function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_) { assembly { value_ := sload(slot_) } } function _setSlotValue(bytes32 slot_, bytes32 value_) internal { assembly { sstore(slot_, value_) } } /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _delegate(address implementation__) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation__, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } receive() external payable {} /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _delegate(_getAddress(IMPLEMENTATION_SLOT)); } }
File 2 of 2: JollySwap
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.7; contract JollySwap { bytes32 private constant ADMIN_SLOT = bytes32(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103); uint256 private constant ONE_PERCENT = type(uint256).max / 100; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event Minted(address indexed owner, uint256 id); event Burned(address indexed owner, uint256 id); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint256 public totalSupply; uint256 public randmness; mapping(uint256 => TokenData) internal tokens; mapping(address => UserData) internal users; mapping(address => bool) public minters; mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; struct TokenData { address owner; } struct UserData { uint128 balance; uint128 minted; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR & MODIFIERS //////////////////////////////////////////////////////////////*/ function initialize(string memory _name, string memory _symbol) external { require(msg.sender == owner(), "NOT AUTHORIZED"); name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ function balanceOf(address owner_) public view virtual returns (uint256) { require(owner_ != address(0), "ZERO_ADDRESS"); return users[owner_].balance; } function minted(address owner_) public view returns (uint256) { return users[owner_].minted; } function rarity(uint256 id) public view returns (uint256) { if (randmness == 0) return 0; uint256 rdn = uint256(keccak256(abi.encodePacked(id, randmness))); if (rdn > ONE_PERCENT * 98) return 3; if (rdn > ONE_PERCENT * 80) return 2; return 1; } function owner() public view returns (address owner_) { return _getAddress(ADMIN_SLOT); } function ownerOf(uint256 id) public view returns (address owner_) { require((owner_ = tokens[id].owner) != address(0), "NOT_MINTED"); } function tokenURI(uint256 id) public view virtual returns (string memory) { return string(abi.encodePacked("https://northpole-qa.jollyswap.xyz/nft/hohoho/", _toString(id), "/", _toString(rarity(id)), ".json")); } /*////////////////////////////////////////////////////////////// MINTING LOGIC //////////////////////////////////////////////////////////////*/ function mint(address receiver) external { require(minters[msg.sender], "NOT MINTER"); emit Minted(receiver, ++totalSupply); _safeMint(receiver, totalSupply); } function burn(address owner_, uint256 id) external { require(minters[msg.sender], "NOT MINTER"); require(ownerOf(id) == owner_, "NOT OWNER"); emit Burned(owner_, id); _burn(id); } /*////////////////////////////////////////////////////////////// ADMIN LOGIC //////////////////////////////////////////////////////////////*/ function withdraw(address destination, uint256 amount) external { require(msg.sender == owner(), "NOT_ADMIN"); (bool success, ) = destination.call{value: amount}(""); require(success, "TRANSFER FAILED"); } function addMinter(address minter_, bool allowed) external { require(msg.sender == owner(), "NOT_ADMIN"); minters[minter_] = allowed; } function setRandomness(uint256 randomness) external { require(msg.sender == owner(), "NOT_ADMIN"); randmness = randomness; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner_ = tokens[id].owner; require(msg.sender == owner_ || isApprovedForAll[owner_][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner_, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == tokens[id].owner, "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { users[from].balance--; users[to].balance++; } tokens[id].owner = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(tokens[id].owner == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { users[to].minted++; users[to].balance++; } tokens[id].owner = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner_ = tokens[id].owner; require(owner_ != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { users[owner_].balance--; } tokens[id].owner = address(0); delete getApproved[id]; emit Transfer(owner_, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// INTERNAL UTILITIES //////////////////////////////////////////////////////////////*/ function _toString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } function _getAddress(bytes32 key) internal view returns (address add) { add = address(uint160(uint256(_getSlotValue(key)))); } function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_) { assembly { value_ := sload(slot_) } } } abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }