Transaction Hash:
Block:
19716943 at Apr-23-2024 08:36:35 AM +UTC
Transaction Fee:
0.000553495975163851 ETH
$1.35
Gas Used:
46,457 Gas / 11.914156643 Gwei
Emitted Events:
183 |
CredefiToken.Approval( owner=[Sender] 0xed5ccd9bde541a29ca9e1d10a449fe96c24f1b03, spender=0x00000000...43aC78BA3, value=115792089237316195423570985008687907853269984665640564039457584007913129639935 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x4838B106...B0BAD5f97
Miner
| (Titan Builder) | 8.288533126243404529 Eth | 8.288628152074932505 Eth | 0.000095025831527976 | |
0xaE6e307c...49c014c6B | |||||
0xEd5CCd9B...6C24F1b03 |
0.01163 Eth
Nonce: 0
|
0.011076504024836149 Eth
Nonce: 1
| 0.000553495975163851 |
Execution Trace
CredefiToken.approve( spender=0x000000000022D473030F116dDEE9F6B43aC78BA3, value=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
{"CredefiToken.sol":{"content":"// SPDX-License-Identifier:MIT\npragma solidity 0.8.10;\n\nimport \"./IERC20.sol\";\n\ncontract CredefiToken is IERC20 {\n // bytes32 private constant EIP712DOMAIN_HASH =\n // keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")\n bytes32 private constant EIP712DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n // bytes32 private constant NAME_HASH = keccak256(\"Credi\")\n bytes32 private constant NAME_HASH = 0x3c5eac0879bc46be0fe2a2701e57d8e6edcaa427c79074f4513eb9572ff50507;\n\n // bytes32 private constant VERSION_HASH = keccak256(\"1\")\n bytes32 private constant VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\n\n // bytes32 public constant PERMIT_TYPEHASH =\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n // bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH =\n // keccak256(\"TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)\");\n bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH =\n 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;\n\n string public constant name = \"CREDI\";\n string public constant symbol = \"CREDI\";\n uint8 public constant decimals = 18;\n\n address public timelock;\n uint256 public override totalSupply;\n\n mapping(address =\u003e uint256) public override balanceOf;\n mapping(address =\u003e mapping(address =\u003e uint256)) public override allowance;\n\n // ERC-2612, ERC-3009 state\n mapping(address =\u003e uint256) public nonces;\n mapping(address =\u003e mapping(bytes32 =\u003e bool)) public authorizationState;\n\n event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);\n event TimelockUpdated(address indexed timelock);\n\n modifier onlyTimelock() {\n require(msg.sender == address(timelock), \"CREDI:NOT_TIMELOCK\");\n _;\n }\n\n constructor(address _timelock) {\n _changeTimelock(_timelock);\n }\n\n function changeTimelock(address _timelock) external onlyTimelock {\n _changeTimelock(_timelock);\n }\n\n function mint(address to, uint256 value) external onlyTimelock returns (bool) {\n _mint(to, value);\n return true;\n }\n\n function burn(uint256 value) external returns (bool) {\n _burn(msg.sender, value);\n return true;\n }\n\n function approve(address spender, uint256 value) external override returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transfer(address to, uint256 value) external override returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external override returns (bool) {\n uint256 fromAllowance = allowance[from][msg.sender];\n if (fromAllowance != type(uint256).max) {\n // Allowance is implicitly checked with Solidity\u0027s underflow protection\n allowance[from][msg.sender] = fromAllowance - value;\n }\n _transfer(from, to, value);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline \u003e= block.timestamp, \"CREDI:AUTH_EXPIRED\");\n\n bytes32 encodeData = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner], deadline));\n nonces[owner] = nonces[owner] + 1;\n _validateSignedData(owner, encodeData, v, r, s);\n\n _approve(owner, spender, value);\n }\n\n function transferWithAuthorization(\n address from,\n address to,\n uint256 value,\n uint256 validAfter,\n uint256 validBefore,\n bytes32 nonce,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(block.timestamp \u003e validAfter, \"CREDI:AUTH_NOT_YET_VALID\");\n require(block.timestamp \u003c validBefore, \"CREDI:AUTH_EXPIRED\");\n require(!authorizationState[from][nonce], \"CREDI:AUTH_ALREADY_USED\");\n\n bytes32 encodeData = keccak256(\n abi.encode(TRANSFER_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce)\n );\n _validateSignedData(from, encodeData, v, r, s);\n\n authorizationState[from][nonce] = true;\n emit AuthorizationUsed(from, nonce);\n\n _transfer(from, to, value);\n }\n\n function getChainId() public view returns (uint256 chainId) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n function getDomainSeparator() public view returns (bytes32) {\n return keccak256(abi.encode(EIP712DOMAIN_HASH, NAME_HASH, VERSION_HASH, getChainId(), address(this)));\n }\n\n function _changeTimelock(address _timelock) internal {\n timelock = _timelock;\n emit TimelockUpdated(_timelock);\n }\n\n function _validateSignedData(\n address signer,\n bytes32 encodeData,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal view {\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", getDomainSeparator(), encodeData));\n address recoveredAddress = ecrecover(digest, v, r, s);\n // Explicitly disallow authorizations for address(0) as ecrecover returns address(0) on malformed messages\n require(recoveredAddress != address(0) \u0026\u0026 recoveredAddress == signer, \"CREDI:INVALID_SIGNATURE\");\n }\n\n function _mint(address to, uint256 value) internal {\n totalSupply = totalSupply + value;\n balanceOf[to] = balanceOf[to] + value;\n emit Transfer(address(0), to, value);\n }\n\n function _burn(address from, uint256 value) internal {\n // Balance is implicitly checked with Solidity\u0027s underflow protection\n balanceOf[from] = balanceOf[from] - value;\n totalSupply = totalSupply - value;\n emit Transfer(from, address(0), value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n ) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(\n address from,\n address to,\n uint256 value\n ) private {\n require(to != address(this) \u0026\u0026 to != address(0), \"CREDI:RECEIVER_IS_TOKEN_OR_ZERO\");\n\n // Balance is implicitly checked with Solidity\u0027s underflow protection\n balanceOf[from] = balanceOf[from] - value;\n balanceOf[to] = balanceOf[to] + value;\n emit Transfer(from, to, value);\n }\n}\n"},"IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller\u0027s account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller\u0027s tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender\u0027s allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller\u0027s\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"}}