019d5666-e916-7246-acfd-c2f7d6ef4d74
Open this run to answer one question: is this real attacker-relevant behavior with real impact, or just normal contract plumbing?
| ID | Type | Status | Attempts | Heartbeat |
|---|---|---|---|---|
| 42960 | artifact.fetch | complete | 1 / 3 | 1 week ago |
| 42961 | proxy.resolve | complete | 1 / 3 | 1 week ago |
| 42962 | tool.cast_disasm | complete | 1 / 3 | 1 week ago |
| 42963 | analysis.bundle | complete | 1 / 3 | 1 week ago |
| 42964 | capability.graph | complete | 1 / 3 | 1 week ago |
| 42965 | detector.run | complete | 1 / 3 | 1 week ago |
| 42966 | validation.fork | complete | 1 / 3 | 1 week ago |
| 43008 | report.consolidate | complete | 1 / 6 | 1 week ago |
| 43009 | tool.slither | complete | 1 / 2 | 1 week ago |
{
"status": "not_proxy"
}
'forge clean' running (wd: /tmp/slither-3rzqsamt)
'forge config --json' running
'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-3rzqsamt)
Wallets.refundGasBySchain(bytes32,address,uint256,bool) (contracts/test/TestWallets.sol#53-68) sends eth to arbitrary user
Dangerous calls:
- spender.transfer(amount) (contracts/test/TestWallets.sol#67)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) has bitwise-xor operator ^ instead of the exponentiation operator **:
- inverse = (3 * denominator) ^ 2 (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#116)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation
SkaleVerifierMock.verify(IFieldOperations.Fp2Point,bytes32,uint256,uint256,uint256,IFieldOperations.G2Point) (contracts/test/SkaleVerifierMock.sol#57-99) uses a Boolean constant improperly:
-require(bool,string)(G1Operations.isG1Point(hashA,hashB) || true,Hash not in G1) (contracts/test/SkaleVerifierMock.sol#84)
SkaleVerifierMock.verify(IFieldOperations.Fp2Point,bytes32,uint256,uint256,uint256,IFieldOperations.G2Point) (contracts/test/SkaleVerifierMock.sol#57-99) uses a Boolean constant improperly:
-require(bool,string)(G1Operations.isG1Point(signature.a,newSignB) || true,Sign not in G1) (contracts/test/SkaleVerifierMock.sol#83)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse = (3 * denominator) ^ 2 (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#116)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse *= 2 - denominator * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#120)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse *= 2 - denominator * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#121)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse *= 2 - denominator * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#122)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse *= 2 - denominator * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#123)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse *= 2 - denominator * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#124)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- denominator = denominator / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#101)
- inverse *= 2 - denominator * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#125)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) performs a multiplication on the result of a division:
- prod0 = prod0 / twos (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#104)
- result = prod0 * inverse (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#131)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply
IERC20TransferVoid (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#35-38) has incorrect ERC20 function interface:IERC20TransferVoid.transferFrom(address,address,uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#36)
IERC20TransferVoid (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#35-38) has incorrect ERC20 function interface:IERC20TransferVoid.transfer(address,uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#37)
ERC20TransferWithoutReturn (contracts/test/erc20/ERC20TransferWithoutReturn.sol#11-24) has incorrect ERC20 function interface:IERC20TransferWithoutReturn.transferFrom(address,address,uint256) (contracts/test/erc20/ERC20TransferWithoutReturn.sol#8)
ERC20TransferWithoutReturn (contracts/test/erc20/ERC20TransferWithoutReturn.sol#11-24) has incorrect ERC20 function interface:ERC20TransferWithoutReturn.transferFrom(address,address,uint256) (contracts/test/erc20/ERC20TransferWithoutReturn.sol#16-23)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface
Reentrancy in FallbackEthTester.receive() (contracts/test/FallbackEthTester.sol#55-62):
External calls:
- communityPool.withdrawFunds(schainName,balance) (contracts/test/FallbackEthTester.sol#59)
State variables written after the call(s):
- _receiveInProgress = false (contracts/test/FallbackEthTester.sol#60)
FallbackEthTester._receiveInProgress (contracts/test/FallbackEthTester.sol#42) can be used in cross function reentrancies:
- FallbackEthTester.receive() (contracts/test/FallbackEthTester.sol#55-62)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1
TokenManagerERC1155._exitBatch(SchainHash,address,address,address,uint256[],uint256[]).isMainChainToken (contracts/schain/TokenManagers/TokenManagerERC1155.sol#476) is a local variable never initialized
Nodes._publicKeyToAddress(bytes32[2]).addr (contracts/test/TestNodes.sol#119) is a local variable never initialized
TokenManagerERC20._exit(SchainHash,address,address,address,uint256).isMainChainToken (contracts/schain/TokenManagers/TokenManagerERC20.sol#323) is a local variable never initialized
TokenManagerERC20._sendERC20(SchainHash,bytes).contractOnSchain (contracts/schain/TokenManagers/TokenManagerERC20.sol#264) is a local variable never initialized
TokenManagerERC1155._exit(SchainHash,address,address,address,uint256,uint256).isMainChainToken (contracts/schain/TokenManagers/TokenManagerERC1155.sol#431) is a local variable never initialized
TokenManagerERC721WithMetadata._exit(SchainHash,address,address,address,uint256).isMainChainToken (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#140) is a local variable never initialized
TokenManagerERC721._exit(SchainHash,address,address,address,uint256).isMainChainToken (contracts/schain/TokenManagers/TokenManagerERC721.sol#327) is a local variable never initialized
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables
AccessControlEnumerableUpgradeable._grantRole(bytes32,address) (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#58-61) ignores return value by _roleMembers[role].add(account) (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#60)
AccessControlEnumerableUpgradeable._revokeRole(bytes32,address) (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#66-69) ignores return value by _roleMembers[role].remove(account) (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#68)
DepositBoxERC1155._addERC1155ForSchain(string,address) (contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol#566-572) ignores return value by _schainToERC1155[schainHash].add(erc1155OnMainnet) (contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol#570)
DepositBoxERC20._addERC20ForSchain(string,address) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#810-816) ignores return value by _schainToERC20[schainHash].add(erc20OnMainnet) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#814)
DepositBoxERC721._addERC721ForSchain(string,address) (contracts/mainnet/DepositBoxes/DepositBoxERC721.sol#332-338) ignores return value by _schainToERC721[schainHash].add(erc721OnMainnet) (contracts/mainnet/DepositBoxes/DepositBoxERC721.sol#336)
TokenManagerERC1155._addERC1155ForSchain(SchainHash,address) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#611-616) ignores return value by _schainToERC1155[chainHash].add(erc1155OnMainChain) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#614)
TokenManagerERC20._addERC20ForSchain(SchainHash,address) (contracts/schain/TokenManagers/TokenManagerERC20.sol#433-438) ignores return value by _schainToERC20[chainHash].add(erc20OnMainChain) (contracts/schain/TokenManagers/TokenManagerERC20.sol#436)
TokenManagerERC721._addERC721ForSchain(SchainHash,address) (contracts/schain/TokenManagers/TokenManagerERC721.sol#307-312) ignores return value by _schainToERC721[chainHash].add(erc721OnMainChain) (contracts/schain/TokenManagers/TokenManagerERC721.sol#310)
TokenManagerERC721WithMetadata._sendERC721(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#78-125) ignores return value by contractOnSchain.setTokenURI(tokenId,tokenURI) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#120)
MessageProxyForMainnet.addReimbursedContract(string,address) (contracts/mainnet/MessageProxyForMainnet.sol#236-249) ignores return value by _reimbursedContracts[schainHash].add(reimbursedContract) (contracts/mainnet/MessageProxyForMainnet.sol#247)
MessageProxyForMainnet.postIncomingMessages(string,uint256,IMessageListener.Message[],IMessageListener.Signature) (contracts/mainnet/MessageProxyForMainnet.sol#283-329) ignores return value by communityPool.refundGasBySchainWallet(fromSchainHash,address(msg.sender),notReimbursedGas) (contracts/mainnet/MessageProxyForMainnet.sol#328)
MessageProxyForMainnet._removeReimbursedContract(SchainHash,address) (contracts/mainnet/MessageProxyForMainnet.sol#565-568) ignores return value by _reimbursedContracts[schainHash].remove(reimbursedContract) (contracts/mainnet/MessageProxyForMainnet.sol#566)
MessageProxy.registerExtraContractForAll(address) (contracts/MessageProxy.sol#191-199) ignores return value by _getRegistryContracts()[SchainHash.wrap(bytes32(0))].add(extraContract) (contracts/MessageProxy.sol#197)
MessageProxy.removeExtraContractForAll(address) (contracts/MessageProxy.sol#209-216) ignores return value by _getRegistryContracts()[SchainHash.wrap(bytes32(0))].remove(extraContract) (contracts/MessageProxy.sol#214)
MessageProxy._registerExtraContract(SchainHash,address) (contracts/MessageProxy.sol#398-413) ignores return value by _getRegistryContracts()[chainHash].add(extraContract) (contracts/MessageProxy.sol#411)
MessageProxy._removeExtraContract(SchainHash,address) (contracts/MessageProxy.sol#423-432) ignores return value by _getRegistryContracts()[chainHash].remove(extraContract) (contracts/MessageProxy.sol#430)
MessageProxyForMainnetTester.refundGasByUser(SchainHash,address,address,uint256) (contracts/test/MessageProxyForMainnetTester.sol#39-49) ignores return value by communityPool.refundGasByUser(fromSchainHash,node,user,gas) (contracts/test/MessageProxyForMainnetTester.sol#48)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return
ERC1155OnChain.constructor(string).uri (contracts/schain/tokens/ERC1155OnChain.sol#42) shadows:
- ERC1155Upgradeable.uri(uint256) (@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#64-66) (function)
- IERC1155MetadataURIUpgradeable.uri(uint256) (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol#21) (function)
RevertableERC20.constructor(string,string).name (contracts/test/erc20/RevertableERC20.sol#35) shadows:
- ERC20Upgradeable.name() (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#67-69) (function)
- IERC20MetadataUpgradeable.name() (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol#17) (function)
RevertableERC20.constructor(string,string).symbol (contracts/test/erc20/RevertableERC20.sol#35) shadows:
- ERC20Upgradeable.symbol() (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#75-77) (function)
- IERC20MetadataUpgradeable.symbol() (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol#22) (function)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing
Wallets.refundGasBySchain(bytes32,address,uint256,bool).spender (contracts/test/TestWallets.sol#55) lacks a zero-check on :
- spender.transfer(amount) (contracts/test/TestWallets.sol#67)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation
DepositBoxERC20._doNTransfers(DepositBoxERC20.DelayedTransfer[],uint256[],uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#725-741) has external calls inside a loop: this.doTransfer(transfer.token,transfer.receiver,transfer.amount) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#734-739)
Calls stack containing the loop:
DepositBoxERC20.retrieve()
DepositBoxERC20.retrieveFor(address)
DepositBoxERC20._doNTransfers(DepositBoxERC20.DelayedTransfer[],uint256[],uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#725-741) has external calls inside a loop: this.doTransfer(transfer.token,transfer.receiver,transfer.amount) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#734-739)
Calls stack containing the loop:
DepositBoxERC20.retrieveFor(address)
Linker.connectSchain(string,address[]) (contracts/mainnet/Linker.sol#92-105) has external calls inside a loop: Twin(_mainnetContracts.at(i)).addSchainContract(schainName,schainContracts[i]) (contracts/mainnet/Linker.sol#102)
Linker.disconnectSchain(string) (contracts/mainnet/Linker.sol#148-154) has external calls inside a loop: Twin(_mainnetContracts.at(i)).removeSchainContract(schainName) (contracts/mainnet/Linker.sol#151)
Linker.hasSchain(string) (contracts/mainnet/Linker.sol#173-179) has external calls inside a loop: connected = connected && Twin(_mainnetContracts.at(i)).hasSchainContract(schainName) (contracts/mainnet/Linker.sol#177)
TokenManagerLinker.connectSchain(string) (contracts/schain/TokenManagerLinker.sol#144-155) has external calls inside a loop: tokenManagers[i].addTokenManager(schainName,address(tokenManagers[i])) (contracts/schain/TokenManagerLinker.sol#152)
TokenManagerLinker.disconnectSchain(string) (contracts/schain/TokenManagerLinker.sol#164-170) has external calls inside a loop: tokenManagers[i].removeTokenManager(schainName) (contracts/schain/TokenManagerLinker.sol#167)
TokenManagerLinker.hasSchain(string) (contracts/schain/TokenManagerLinker.sol#190-197) has external calls inside a loop: connected = connected && tokenManagers[i].hasTokenManager(schainName) (contracts/schain/TokenManagerLinker.sol#194)
MessageProxy._getGasPayer(SchainHash,IMessageListener.Message,uint256) (contracts/MessageProxy.sol#497-530) has external calls inside a loop: receiver = IGasReimbursable(message.destinationContract).gasPayer{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#505-529)
Calls stack containing the loop:
MessageProxyForMainnet.postIncomingMessages(string,uint256,IMessageListener.Message[],IMessageListener.Signature)
MessageProxy._callReceiverContract(SchainHash,IMessageListener.Message,uint256) (contracts/MessageProxy.sol#456-492) has external calls inside a loop: IMessageReceiver(message.destinationContract).postMessage{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#470-491)
Calls stack containing the loop:
MessageProxyForMainnet.postIncomingMessages(string,uint256,IMessageListener.Message[],IMessageListener.Signature)
MessageProxyForMainnet.postIncomingMessages(string,uint256,IMessageListener.Message[],IMessageListener.Signature) (contracts/mainnet/MessageProxyForMainnet.sol#283-329) has external calls inside a loop: notReimbursedGas += communityPool.refundGasByUser(fromSchainHash,address(msg.sender),receiver,gasTotal - gasleft()() + additionalGasPerMessage) (contracts/mainnet/MessageProxyForMainnet.sol#317-322)
MessageProxy._callReceiverContract(SchainHash,IMessageListener.Message,uint256) (contracts/MessageProxy.sol#456-492) has external calls inside a loop: IMessageReceiver(message.destinationContract).postMessage{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#470-491)
Calls stack containing the loop:
MessageProxyForSchain.postIncomingMessages(string,uint256,IMessageListener.Message[],IMessageListener.Signature)
SchainsInternal.addNodesToSchainsGroups(bytes32,uint256[]) (contracts/test/TestSchainsInternal.sol#94-101) has external calls inside a loop: nodeAddress = nodesContract.getNodeAddress(nodes[i]) (contracts/test/TestSchainsInternal.sol#98)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop
Reentrancy in FallbackEthTester.getMyEth() (contracts/test/FallbackEthTester.sol#72-76):
External calls:
- depositBoxEth.getMyEth() (contracts/test/FallbackEthTester.sol#74)
State variables written after the call(s):
- _getMyEthInProgress = false (contracts/test/FallbackEthTester.sol#75)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2
Reentrancy in MessageProxy._callReceiverContract(SchainHash,IMessageListener.Message,uint256) (contracts/MessageProxy.sol#456-492):
External calls:
- IMessageReceiver(message.destinationContract).postMessage{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#470-491)
Event emitted after the call(s):
- PostMessageError(counter,_getSlice(bytes(reason),REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#477-480)
- PostMessageError(counter,abi.encodePacked(errorCode)) (contracts/MessageProxy.sol#482-485)
- PostMessageError(counter,_getSlice(revertData,REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#487-490)
Reentrancy in DepositBoxERC20._doNTransfers(DepositBoxERC20.DelayedTransfer[],uint256[],uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#725-741):
External calls:
- this.doTransfer(transfer.token,transfer.receiver,transfer.amount) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#734-739)
Event emitted after the call(s):
- TransferSkipped(transfersIds[i]) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#738)
- TransferSucceeded(transfersIds[i]) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#735)
Reentrancy in MessageProxy._getGasPayer(SchainHash,IMessageListener.Message,uint256) (contracts/MessageProxy.sol#497-530):
External calls:
- receiver = IGasReimbursable(message.destinationContract).gasPayer{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#505-529)
Event emitted after the call(s):
- PostMessageError(counter,_getSlice(bytes(reason),REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#512-515)
- PostMessageError(counter,abi.encodePacked(errorCode)) (contracts/MessageProxy.sol#518-521)
- PostMessageError(counter,_getSlice(revertData,REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#524-527)
Reentrancy in TokenManagerERC1155._sendERC1155(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#315-365):
External calls:
- IERC1155Upgradeable(token).safeTransferFrom(address(this),receiver,id,amount,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#352)
- contractOnSchain.mint(receiver,id,amount,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#354)
Event emitted after the call(s):
- ERC1155TokenReceived(fromChainHash,token,address(contractOnSchain),_asSingletonArray(id),_asSingletonArray(amount)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#356-362)
Reentrancy in TokenManagerERC1155._sendERC1155Batch(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#373-416):
External calls:
- IERC1155Upgradeable(token).safeBatchTransferFrom(address(this),receiver,ids,amounts,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#409)
- contractOnSchain.mintBatch(receiver,ids,amounts,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#411)
Event emitted after the call(s):
- ERC1155TokenReceived(fromChainHash,token,address(contractOnSchain),ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#413)
Reentrancy in TokenManagerERC20._sendERC20(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC20.sol#261-309):
External calls:
- contractOnSchain.mint(receiver,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#296)
- require(bool,string)(ERC20Upgradeable(token).transfer(receiver,amount),Transfer was failed) (contracts/schain/TokenManagers/TokenManagerERC20.sol#301-304)
Event emitted after the call(s):
- ERC20TokenReceived(fromChainHash,token,address(contractOnSchain),amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#306)
Reentrancy in TokenManagerERC721._sendERC721(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC721.sol#212-254):
External calls:
- IERC721Upgradeable(token).transferFrom(address(this),receiver,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#247)
- contractOnSchain.mint(receiver,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#249)
Event emitted after the call(s):
- ERC721TokenReceived(fromChainHash,token,address(contractOnSchain),tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#251)
Reentrancy in TokenManagerERC721WithMetadata._sendERC721(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#78-125):
External calls:
- IERC721Upgradeable(token).transferFrom(address(this),receiver,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#117)
- contractOnSchain.mint(receiver,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#119)
- contractOnSchain.setTokenURI(tokenId,tokenURI) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#120)
Event emitted after the call(s):
- ERC721TokenReceived(fromChainHash,token,address(contractOnSchain),tokenId) (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#122)
Reentrancy in TokenManagerERC1155.exitToMainERC1155(address,uint256,uint256) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#109-119):
External calls:
- communityLocker.checkAllowedToSendMessage(MAINNET_HASH,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#117)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#118)
- contractOnSchain.safeTransferFrom(msg.sender,address(this),id,amount,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#456)
- contractOnSchain.burn(msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#458)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#460)
Event emitted after the call(s):
- ERC1155TokenAdded(chainHash,erc1155OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#615)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#118)
- ERC1155TokenReady(chainHash,erc1155OnMainChain,_asSingletonArray(id),_asSingletonArray(amount)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#564)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#118)
Reentrancy in TokenManagerERC1155.exitToMainERC1155Batch(address,uint256[],uint256[]) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#126-136):
External calls:
- communityLocker.checkAllowedToSendMessage(MAINNET_HASH,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#134)
- _exitBatch(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#135)
- contractOnSchain.safeBatchTransferFrom(msg.sender,address(this),ids,amounts,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#496)
- contractOnSchain.burnBatch(msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#498)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#500)
Event emitted after the call(s):
- ERC1155TokenAdded(chainHash,erc1155OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#615)
- _exitBatch(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#135)
- ERC1155TokenReady(chainHash,erc1155OnMainChain,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#599)
- _exitBatch(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#135)
Reentrancy in TokenManagerERC20.exitToMainERC20(address,uint256) (contracts/schain/TokenManagers/TokenManagerERC20.sol#105-114):
External calls:
- communityLocker.checkAllowedToSendMessage(MAINNET_HASH,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC20.sol#112)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#113)
- require(bool,string)(contractOnSchain.transferFrom(msg.sender,address(this),amount),Transfer was failed) (contracts/schain/TokenManagers/TokenManagerERC20.sol#349-352)
- require(bool,string)(contractOnSchain.transferFrom(msg.sender,address(this),amount),Transfer was failed) (contracts/schain/TokenManagers/TokenManagerERC20.sol#354-357)
- contractOnSchain.burn(amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#358)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC20.sol#360-364)
Event emitted after the call(s):
- ERC20TokenAdded(chainHash,erc20OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC20.sol#437)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#113)
- ERC20TokenReady(chainHash,erc20OnMainChain,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#421)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#113)
Reentrancy in TokenManagerERC721.exitToMainERC721(address,uint256) (contracts/schain/TokenManagers/TokenManagerERC721.sol#97-106):
External calls:
- communityLocker.checkAllowedToSendMessage(MAINNET_HASH,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC721.sol#104)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#105)
- contractOnSchain.transferFrom(msg.sender,address(this),tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#346)
- contractOnSchain.transferFrom(msg.sender,address(this),tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#348)
- contractOnSchain.burn(tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#349)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC721.sol#351)
Event emitted after the call(s):
- ERC721TokenAdded(chainHash,erc721OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC721.sol#311)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#105)
- ERC721TokenReady(chainHash,erc721OnMainChain,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#295)
- _exit(MAINNET_HASH,depositBox,contractOnMainnet,msg.sender,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#105)
Reentrancy in MessageProxyForMainnet.postIncomingMessages(string,uint256,IMessageListener.Message[],IMessageListener.Signature) (contracts/mainnet/MessageProxyForMainnet.sol#283-329):
External calls:
- receiver = _getGasPayer(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#315)
- receiver = IGasReimbursable(message.destinationContract).gasPayer{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#505-529)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#316)
- IMessageReceiver(message.destinationContract).postMessage{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#470-491)
- notReimbursedGas += communityPool.refundGasByUser(fromSchainHash,address(msg.sender),receiver,gasTotal - gasleft()() + additionalGasPerMessage) (contracts/mainnet/MessageProxyForMainnet.sol#317-322)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#324)
- IMessageReceiver(message.destinationContract).postMessage{gas: gasLimit}(schainHash,message.sender,message.data) (contracts/MessageProxy.sol#470-491)
Event emitted after the call(s):
- PostMessageError(counter,Destination contract is not a contract) (contracts/MessageProxy.sol#464-467)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#324)
- PostMessageError(counter,Destination contract is not a contract) (contracts/MessageProxy.sol#464-467)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#316)
- PostMessageError(counter,_getSlice(bytes(reason),REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#512-515)
- receiver = _getGasPayer(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#315)
- PostMessageError(counter,abi.encodePacked(errorCode)) (contracts/MessageProxy.sol#518-521)
- receiver = _getGasPayer(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#315)
- PostMessageError(counter,_getSlice(bytes(reason),REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#477-480)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#316)
- PostMessageError(counter,_getSlice(bytes(reason),REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#477-480)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#324)
- PostMessageError(counter,abi.encodePacked(errorCode)) (contracts/MessageProxy.sol#482-485)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#324)
- PostMessageError(counter,_getSlice(revertData,REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#524-527)
- receiver = _getGasPayer(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#315)
- PostMessageError(counter,abi.encodePacked(errorCode)) (contracts/MessageProxy.sol#482-485)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#316)
- PostMessageError(counter,_getSlice(revertData,REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#487-490)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#316)
- PostMessageError(counter,_getSlice(revertData,REVERT_REASON_LENGTH)) (contracts/MessageProxy.sol#487-490)
- _callReceiverContract(fromSchainHash,messages[i],startingCounter + i) (contracts/mainnet/MessageProxyForMainnet.sol#324)
Reentrancy in TokenManagerERC1155.transferToSchainERC1155(string,address,uint256,uint256) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#144-157):
External calls:
- communityLocker.checkAllowedToSendMessage(targetSchainHash,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#155)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#156)
- contractOnSchain.safeTransferFrom(msg.sender,address(this),id,amount,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#456)
- contractOnSchain.burn(msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#458)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#460)
Event emitted after the call(s):
- ERC1155TokenAdded(chainHash,erc1155OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#615)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#156)
- ERC1155TokenReady(chainHash,erc1155OnMainChain,_asSingletonArray(id),_asSingletonArray(amount)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#564)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,id,amount) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#156)
Reentrancy in TokenManagerERC1155.transferToSchainERC1155Batch(string,address,uint256[],uint256[]) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#165-178):
External calls:
- communityLocker.checkAllowedToSendMessage(targetSchainHash,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#176)
- _exitBatch(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#177)
- contractOnSchain.safeBatchTransferFrom(msg.sender,address(this),ids,amounts,) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#496)
- contractOnSchain.burnBatch(msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#498)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#500)
Event emitted after the call(s):
- ERC1155TokenAdded(chainHash,erc1155OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#615)
- _exitBatch(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#177)
- ERC1155TokenReady(chainHash,erc1155OnMainChain,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#599)
- _exitBatch(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,ids,amounts) (contracts/schain/TokenManagers/TokenManagerERC1155.sol#177)
Reentrancy in TokenManagerERC721.transferToSchainERC721(string,address,uint256) (contracts/schain/TokenManagers/TokenManagerERC721.sol#114-126):
External calls:
- communityLocker.checkAllowedToSendMessage(targetSchainHash,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC721.sol#124)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#125)
- contractOnSchain.transferFrom(msg.sender,address(this),tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#346)
- contractOnSchain.transferFrom(msg.sender,address(this),tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#348)
- contractOnSchain.burn(tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#349)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC721.sol#351)
Event emitted after the call(s):
- ERC721TokenAdded(chainHash,erc721OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC721.sol#311)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#125)
- ERC721TokenReady(chainHash,erc721OnMainChain,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#295)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,msg.sender,tokenId) (contracts/schain/TokenManagers/TokenManagerERC721.sol#125)
Reentrancy in TokenManagerERC20.transferToSchainHashERC20Direct(SchainHash,address,uint256,address) (contracts/schain/TokenManagers/TokenManagerERC20.sol#239-251):
External calls:
- communityLocker.checkAllowedToSendMessage(targetSchainHash,msg.sender) (contracts/schain/TokenManagers/TokenManagerERC20.sol#249)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,receiver,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#250)
- require(bool,string)(contractOnSchain.transferFrom(msg.sender,address(this),amount),Transfer was failed) (contracts/schain/TokenManagers/TokenManagerERC20.sol#349-352)
- require(bool,string)(contractOnSchain.transferFrom(msg.sender,address(this),amount),Transfer was failed) (contracts/schain/TokenManagers/TokenManagerERC20.sol#354-357)
- contractOnSchain.burn(amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#358)
- messageProxy.postOutgoingMessage(chainHash,messageReceiver,data) (contracts/schain/TokenManagers/TokenManagerERC20.sol#360-364)
Event emitted after the call(s):
- ERC20TokenAdded(chainHash,erc20OnMainChain,address(0)) (contracts/schain/TokenManagers/TokenManagerERC20.sol#437)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,receiver,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#250)
- ERC20TokenReady(chainHash,erc20OnMainChain,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#421)
- _exit(targetSchainHash,tokenManagers[targetSchainHash],contractOnMainnet,receiver,amount) (contracts/schain/TokenManagers/TokenManagerERC20.sol#250)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3
DepositBoxERC20.escalate(uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#392-405) uses timestamp for comparisons
Dangerous comparisons:
- require(bool,string)(hasRole(ARBITER_ROLE,msg.sender) || isSchainOwner(msg.sender,schainHash),Not enough permissions to request escalation) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#394-397)
- require(bool,string)(delayedTransfers[transferId].status == DelayedTransferStatus.DELAYED,The transfer has to be delayed) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#398)
DepositBoxERC20.validateTransfer(uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#415-427) uses timestamp for comparisons
Dangerous comparisons:
- require(bool,string)(transfer.status == DelayedTransferStatus.ARBITRAGE,Arbitrage has to be active) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#423)
DepositBoxERC20.rejectTransfer(uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#437-450) uses timestamp for comparisons
Dangerous comparisons:
- require(bool,string)(transfer.status == DelayedTransferStatus.ARBITRAGE,Arbitrage has to be active) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#445)
DepositBoxERC20.retrieveFor(address) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#609-652) uses timestamp for comparisons
Dangerous comparisons:
- transfer.status != DelayedTransferStatus.COMPLETED (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#622)
- block.timestamp < transfer.untilTimestamp (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#623)
- transfer.status == DelayedTransferStatus.DELAYED (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#627)
DepositBoxERC20._addToDelayedQueueWithPriority(DoubleEndedQueueUpgradeable.Bytes32Deque,uint256,uint256,uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#837-856) uses timestamp for comparisons
Dangerous comparisons:
- delayedTransfers[uint256(queue.back())].untilTimestamp <= until (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#848)
CommunityLocker.setGasPrice(uint256,uint256,IMessageListener.Signature) (contracts/schain/CommunityLocker.sol#252-274) uses timestamp for comparisons
Dangerous comparisons:
- require(bool,string)(timestamp <= block.timestamp,Timestamp should not be in the future) (contracts/schain/CommunityLocker.sol#261)
Nodes._checkNodeIndex(uint256) (contracts/test/TestNodes.sol#113-115) uses timestamp for comparisons
Dangerous comparisons:
- require(bool,string)(nodeIndex < nodes.length,Node with such index does not exist) (contracts/test/TestNodes.sol#114)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp
ERC721Upgradeable._checkOnERC721Received(address,address,uint256,bytes) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#404-426) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#418-420)
AddressUpgradeable._revert(bytes,string) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#231-243) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#236-239)
StringsUpgradeable.toString(uint256) (@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol#19-39) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol#25-27)
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol#31-33)
MathUpgradeable.mulDiv(uint256,uint256,uint256) (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#55-134) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#62-66)
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#85-92)
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#99-108)
EnumerableSetUpgradeable.values(EnumerableSetUpgradeable.Bytes32Set) (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#219-229) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#224-226)
EnumerableSetUpgradeable.values(EnumerableSetUpgradeable.AddressSet) (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#293-303) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#298-300)
EnumerableSetUpgradeable.values(EnumerableSetUpgradeable.UintSet) (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#367-377) uses assembly
- INLINE ASM (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#372-374)
KeyStorage._getConfigVariableUint256(string) (contracts/schain/KeyStorage.sol#73-95) uses assembly
- INLINE ASM (contracts/schain/KeyStorage.sol#84-93)
KeyStorage._getCurrentBLSPublicKey() (contracts/schain/KeyStorage.sol#100-125) uses assembly
- INLINE ASM (contracts/schain/KeyStorage.sol#112-119)
Precompiled.bn256Pairing(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) (contracts/schain/bls/Precompiled.sol#40-76) uses assembly
- INLINE ASM (contracts/schain/bls/Precompiled.sol#71-73)
ConfigReader.getConfigVariableUint256(string) (contracts/test/ConfigReader.sol#35-57) uses assembly
- INLINE ASM (contracts/test/ConfigReader.sol#46-55)
ConfigReader.getConfigVariableAddress(string) (contracts/test/ConfigReader.sol#59-81) uses assembly
- INLINE ASM (contracts/test/ConfigReader.sol#70-79)
ConfigReader.getConfigVariableString(string) (contracts/test/ConfigReader.sol#83-105) uses assembly
- INLINE ASM (contracts/test/ConfigReader.sol#88-103)
ConfigReader.getConfigPermissionFlag(address,string) (contracts/test/ConfigReader.sol#107-133) uses assembly
- INLINE ASM (contracts/test/ConfigReader.sol#120-131)
Logger.logTextMessage(uint256,string) (contracts/test/Logger.sol#31-54) uses assembly
- INLINE ASM (contracts/test/Logger.sol#37-53)
PrecompiledMock.bigModExp(uint256,uint256,uint256) (contracts/test/PrecompiledMock.sol#27-43) uses assembly
- INLINE ASM (contracts/test/PrecompiledMock.sol#38-40)
PrecompiledMock.bn256ScalarMul(uint256,uint256,uint256) (contracts/test/PrecompiledMock.sol#45-58) uses assembly
- INLINE ASM (contracts/test/PrecompiledMock.sol#53-55)
PrecompiledMock.bn256Pairing(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) (contracts/test/PrecompiledMock.sol#60-96) uses assembly
- INLINE ASM (contracts/test/PrecompiledMock.sol#91-93)
SafeMock.multiSend(bytes) (contracts/test/SafeMock.sol#78-111) uses assembly
- INLINE ASM (contracts/test/SafeMock.sol#81-110)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage
7 different versions of Solidity are used:
- Version constraint ^0.8.0 is used by:
-^0.8.0 (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/interfaces/IERC4906Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/interfaces/IERC721Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol#5)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol#4)
-^0.8.0 (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#5)
-^0.8.0 (@skalenetwork/etherbase-interfaces/IEtherbase.sol#23)
-^0.8.0 (@skalenetwork/etherbase-interfaces/IEtherbaseUpgradeable.sol#23)
- Version constraint ^0.8.2 is used by:
-^0.8.2 (@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol#4)
- Version constraint ^0.8.1 is used by:
-^0.8.1 (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#4)
- Version constraint ^0.8.4 is used by:
-^0.8.4 (@openzeppelin/contracts-upgradeable/utils/structs/DoubleEndedQueueUpgradeable.sol#3)
- Version constraint >=0.8.19<0.9.0 is used by:
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/DomainTypes.sol#21)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IGasReimbursable.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IMessageListener.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IMessageProxy.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IMessageReceiver.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataMainnet.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataSchain.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC1155.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC20.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC721.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxEth.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ICommunityPool.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/IDepositBox.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ILinker.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/IMessageProxyForMainnet.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ISkaleManagerClient.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ITwin.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/ICommunityLocker.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/IKeyStorage.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/IMessageProxyForSchain.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/ITokenManager.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/ITokenManagerLinker.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenContractManager.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC1155.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC20.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC721.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerEth.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/bls/IFieldOperations.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IERC1155OnChain.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IERC20OnChain.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IERC721OnChain.sol#22)
->=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IEthErc20.sol#22)
- Version constraint >=0.6.10<0.9.0 is used by:
->=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/IContractManager.sol#22)
->=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/INodes.sol#22)
->=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/ISchains.sol#22)
->=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/ISchainsInternal.sol#22)
->=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/IWallets.sol#22)
->=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/utils/IRandom.sol#22)
- Version constraint 0.8.27 is used by:
-0.8.27 (contracts/MessageProxy.sol#22)
-0.8.27 (contracts/Messages.sol#22)
-0.8.27 (contracts/extensions/ERC721ReferenceMintAndMetadataMainnet.sol#22)
-0.8.27 (contracts/extensions/ERC721ReferenceMintAndMetadataSchain.sol#22)
-0.8.27 (contracts/extensions/interfaces/MessageProxyClient.sol#22)
-0.8.27 (contracts/extensions/interfaces/MessageReceiver.sol#22)
-0.8.27 (contracts/extensions/interfaces/MessageSender.sol#22)
-0.8.27 (contracts/mainnet/CommunityPool.sol#24)
-0.8.27 (contracts/mainnet/DepositBox.sol#23)
-0.8.27 (contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol#22)
-0.8.27 (contracts/mainnet/DepositBoxes/DepositBoxERC20.sol#22)
-0.8.27 (contracts/mainnet/DepositBoxes/DepositBoxERC721.sol#22)
-0.8.27 (contracts/mainnet/DepositBoxes/DepositBoxERC721WithMetadata.sol#22)
-0.8.27 (contracts/mainnet/DepositBoxes/DepositBoxEth.sol#22)
-0.8.27 (contracts/mainnet/Linker.sol#22)
-0.8.27 (contracts/mainnet/MessageProxyForMainnet.sol#22)
-0.8.27 (contracts/mainnet/SkaleManagerClient.sol#22)
-0.8.27 (contracts/mainnet/Twin.sol#24)
-0.8.27 (contracts/schain/CommunityLocker.sol#24)
-0.8.27 (contracts/schain/DefaultAddresses.sol#22)
-0.8.27 (contracts/schain/KeyStorage.sol#22)
-0.8.27 (contracts/schain/MessageProxyForSchain.sol#22)
-0.8.27 (contracts/schain/TokenManager.sol#22)
-0.8.27 (contracts/schain/TokenManagerLinker.sol#22)
-0.8.27 (contracts/schain/TokenManagers/TokenManagerERC1155.sol#22)
-0.8.27 (contracts/schain/TokenManagers/TokenManagerERC20.sol#22)
-0.8.27 (contracts/schain/TokenManagers/TokenManagerERC721.sol#22)
-0.8.27 (contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol#22)
-0.8.27 (contracts/schain/TokenManagers/TokenManagerEth.sol#22)
-0.8.27 (contracts/schain/bls/FieldOperations.sol#23)
-0.8.27 (contracts/schain/bls/Precompiled.sol#22)
-0.8.27 (contracts/schain/bls/SkaleVerifier.sol#22)
-0.8.27 (contracts/schain/tokens/ERC1155OnChain.sol#23)
-0.8.27 (contracts/schain/tokens/ERC20OnChain.sol#23)
-0.8.27 (contracts/schain/tokens/ERC721OnChain.sol#23)
-0.8.27 (contracts/schain/tokens/EthErc20.sol#22)
-0.8.27 (contracts/test/ConfigReader.sol#23)
-0.8.27 (contracts/test/EtherbaseMock.sol#22)
-0.8.27 (contracts/test/FallbackEthTester.sol#23)
-0.8.27 (contracts/test/KeyStorageMock.sol#22)
-0.8.27 (contracts/test/Logger.sol#23)
-0.8.27 (contracts/test/MessageProxyCaller.sol#22)
-0.8.27 (contracts/test/MessageProxyForMainnetTester.sol#22)
-0.8.27 (contracts/test/MessageProxyForSchainTester.sol#22)
-0.8.27 (contracts/test/MessageProxyForSchainWithoutSignature.sol#22)
-0.8.27 (contracts/test/MessagesTester.sol#23)
-0.8.27 (contracts/test/PrecompiledMock.sol#22)
-0.8.27 (contracts/test/ReceiverGasLimitMainnetMock.sol#23)
-0.8.27 (contracts/test/ReceiverGasLimitSchainMock.sol#23)
-0.8.27 (contracts/test/ReceiverMock.sol#23)
-0.8.27 (contracts/test/SafeMock.sol#22)
-0.8.27 (contracts/test/SkaleManagerMock.sol#22)
-0.8.27 (contracts/test/SkaleVerifierMock.sol#23)
-0.8.27 (contracts/test/TestCallReceiverContract.sol#23)
-0.8.27 (contracts/test/TestContractManager.sol#22)
-0.8.27 (contracts/test/TestNodes.sol#23)
-0.8.27 (contracts/test/TestSchains.sol#23)
-0.8.27 (contracts/test/TestSchainsInternal.sol#23)
-0.8.27 (contracts/test/TestWallets.sol#22)
-0.8.27 (contracts/test/erc20/ERC20IncorrectTransfer.sol#3)
-0.8.27 (contracts/test/erc20/ERC20TransferWithFalseReturn.sol#3)
-0.8.27 (contracts/test/erc20/ERC20TransferWithoutReturn.sol#3)
-0.8.27 (contracts/test/erc20/ERC20WithoutTransfer.sol#3)
-0.8.27 (contracts/test/erc20/RevertableERC20.sol#22)
-0.8.27 (contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol#3)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used
ReceiverGasLimitMainnetMock.postMessage(SchainHash,address,bytes) (contracts/test/ReceiverGasLimitMainnetMock.sol#30-41) has costly operations inside a loop:
- a ++ (contracts/test/ReceiverGasLimitMainnetMock.sol#39)
ReceiverGasLimitSchainMock.postMessage(SchainHash,address,bytes) (contracts/test/ReceiverGasLimitSchainMock.sol#30-41) has costly operations inside a loop:
- a ++ (contracts/test/ReceiverGasLimitSchainMock.sol#39)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init_unchained() (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#22-23) is never used and should be removed
AccessControlUpgradeable.__AccessControl_init_unchained() (@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#79-80) is never used and should be removed
ContextUpgradeable.__Context_init() (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#18-19) is never used and should be removed
ContextUpgradeable.__Context_init_unchained() (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#21-22) is never used and should be removed
ContextUpgradeable._contextSuffixLength() (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#31-33) is never used and should be removed
ContextUpgradeable._msgData() (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#27-29) is never used and should be removed
DepositBoxERC721._receiveERC721(string,address,address,uint256) (contracts/mainnet/DepositBoxes/DepositBoxERC721.sol#296-321) is never used and should be removed
ERC1155BurnableUpgradeable.__ERC1155Burnable_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol#19-20) is never used and should be removed
ERC1155ReceiverUpgradeable.__ERC1155Receiver_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol#17-18) is never used and should be removed
ERC1155ReceiverUpgradeableWithoutGap.__ERC1155Receiver_init() (contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol#28-31) is never used and should be removed
ERC1155ReceiverUpgradeableWithoutGap.__ERC1155Receiver_init_unchained() (contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol#34-35) is never used and should be removed
ERC165Upgradeable.__ERC165_init() (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#24-25) is never used and should be removed
ERC165Upgradeable.__ERC165_init_unchained() (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#27-28) is never used and should be removed
ERC20BurnableUpgradeable.__ERC20Burnable_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol#19-20) is never used and should be removed
ERC721BurnableUpgradeable.__ERC721Burnable_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol#18-19) is never used and should be removed
ERC721URIStorageUpgradeable.__ERC721URIStorage_init() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#19-20) is never used and should be removed
ERC721URIStorageUpgradeable.__ERC721URIStorage_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#22-23) is never used and should be removed
ERC721Upgradeable.__unsafe_increaseBalance(address,uint256) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#468-470) is never used and should be removed
ERC721Upgradeable._safeMint(address,uint256) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#241-243) is never used and should be removed
ERC721Upgradeable._safeMint(address,uint256,bytes) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#249-255) is never used and should be removed
Initializable._disableInitializers() (@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol#145-151) is never used and should be removed
Initializable._getInitializedVersion() (@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol#156-158) is never used and should be removed
Initializable._isInitializing() (@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol#163-165) is never used and should be removed
KeyStorage._getConfigVariableUint256(string) (contracts/schain/KeyStorage.sol#73-95) is never used and should be removed
KeyStorage._getCurrentBLSPublicKey() (contracts/schain/KeyStorage.sol#100-125) is never used and should be removed
MessageProxyForSchain._getEtherbase() (contracts/schain/MessageProxyForSchain.sol#412-414) is never used and should be removed
MessageProxyForSchain._verifyMessages(bytes32,IMessageListener.Signature) (contracts/schain/MessageProxyForSchain.sol#375-395) is never used and should be removed
TokenManagerERC721._exit(SchainHash,address,address,address,uint256) (contracts/schain/TokenManagers/TokenManagerERC721.sol#317-352) is never used and should be removed
TokenManagerERC721._receiveERC721(SchainHash,address,address,uint256) (contracts/schain/TokenManagers/TokenManagerERC721.sol#273-296) is never used and should be removed
TokenManagerERC721._sendERC721(SchainHash,bytes) (contracts/schain/TokenManagers/TokenManagerERC721.sol#212-254) is never used and should be removed
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code
Version constraint ^0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
- FullInlinerNonExpressionSplitArgumentEvaluationOrder
- MissingSideEffectsOnSelectorAccess
- AbiReencodingHeadOverflowWithStaticArrayCleanup
- DirtyBytesArrayToStorage
- DataLocationChangeInInternalOverride
- NestedCalldataArrayAbiReencodingSizeValidation
- SignedImmutables
- ABIDecodeTwoDimensionalArrayMemory
- KeccakCaching.
It is used by:
- ^0.8.0 (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/interfaces/IERC4906Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/interfaces/IERC721Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol#5)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol#4)
- ^0.8.0 (@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol#5)
- ^0.8.0 (@skalenetwork/etherbase-interfaces/IEtherbase.sol#23)
- ^0.8.0 (@skalenetwork/etherbase-interfaces/IEtherbaseUpgradeable.sol#23)
Version constraint ^0.8.2 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
- FullInlinerNonExpressionSplitArgumentEvaluationOrder
- MissingSideEffectsOnSelectorAccess
- AbiReencodingHeadOverflowWithStaticArrayCleanup
- DirtyBytesArrayToStorage
- DataLocationChangeInInternalOverride
- NestedCalldataArrayAbiReencodingSizeValidation
- SignedImmutables
- ABIDecodeTwoDimensionalArrayMemory
- KeccakCaching.
It is used by:
- ^0.8.2 (@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol#4)
Version constraint ^0.8.1 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
- FullInlinerNonExpressionSplitArgumentEvaluationOrder
- MissingSideEffectsOnSelectorAccess
- AbiReencodingHeadOverflowWithStaticArrayCleanup
- DirtyBytesArrayToStorage
- DataLocationChangeInInternalOverride
- NestedCalldataArrayAbiReencodingSizeValidation
- SignedImmutables
- ABIDecodeTwoDimensionalArrayMemory
- KeccakCaching.
It is used by:
- ^0.8.1 (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#4)
Version constraint ^0.8.4 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
- FullInlinerNonExpressionSplitArgumentEvaluationOrder
- MissingSideEffectsOnSelectorAccess
- AbiReencodingHeadOverflowWithStaticArrayCleanup
- DirtyBytesArrayToStorage
- DataLocationChangeInInternalOverride
- NestedCalldataArrayAbiReencodingSizeValidation
- SignedImmutables.
It is used by:
- ^0.8.4 (@openzeppelin/contracts-upgradeable/utils/structs/DoubleEndedQueueUpgradeable.sol#3)
Version constraint >=0.8.19<0.9.0 is too complex.
It is used by:
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/DomainTypes.sol#21)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IGasReimbursable.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IMessageListener.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IMessageProxy.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/IMessageReceiver.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataMainnet.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataSchain.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC1155.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC20.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC721.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxEth.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ICommunityPool.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/IDepositBox.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ILinker.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/IMessageProxyForMainnet.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ISkaleManagerClient.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/mainnet/ITwin.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/ICommunityLocker.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/IKeyStorage.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/IMessageProxyForSchain.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/ITokenManager.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/ITokenManagerLinker.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenContractManager.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC1155.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC20.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC721.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerEth.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/bls/IFieldOperations.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IERC1155OnChain.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IERC20OnChain.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IERC721OnChain.sol#22)
- >=0.8.19<0.9.0 (@skalenetwork/ima-interfaces/schain/tokens/IEthErc20.sol#22)
Version constraint >=0.6.10<0.9.0 is too complex.
It is used by:
- >=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/IContractManager.sol#22)
- >=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/INodes.sol#22)
- >=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/ISchains.sol#22)
- >=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/ISchainsInternal.sol#22)
- >=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/IWallets.sol#22)
- >=0.6.10<0.9.0 (@skalenetwork/skale-manager-interfaces/utils/IRandom.sol#22)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity
Low level call in SafeERC20Upgradeable._callOptionalReturnBool(IERC20Upgradeable,bytes) (@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol#134-142):
- (success,returndata) = address(token).call(data) (@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol#139)
Low level call in AddressUpgradeable.sendValue(address,uint256) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#64-69):
- (success,None) = recipient.call{value: amount}() (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#67)
Low level call in AddressUpgradeable.functionCallWithValue(address,bytes,uint256,string) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#128-137):
- (success,returndata) = target.call{value: value}(data) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#135)
Low level call in AddressUpgradeable.functionStaticCall(address,bytes,string) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#155-162):
- (success,returndata) = target.staticcall(data) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#160)
Low level call in AddressUpgradeable.functionDelegateCall(address,bytes,string) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#180-187):
- (success,returndata) = target.delegatecall(data) (@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#185)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls
ERC20OnChain (contracts/schain/tokens/ERC20OnChain.sol#34-64) should inherit from IERC20TransferWithFalseReturn (contracts/test/erc20/ERC20TransferWithFalseReturn.sol#7-9)
EthErc20 (contracts/schain/tokens/EthErc20.sol#33-84) should inherit from IERC20TransferWithFalseReturn (contracts/test/erc20/ERC20TransferWithFalseReturn.sol#7-9)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance
Function AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init() (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#19-20) is not in mixedCase
Function AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init_unchained() (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#22-23) is not in mixedCase
Variable AccessControlEnumerableUpgradeable.__gap (@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol#76) is not in mixedCase
Function AccessControlUpgradeable.__AccessControl_init() (@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#76-77) is not in mixedCase
Function AccessControlUpgradeable.__AccessControl_init_unchained() (@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#79-80) is not in mixedCase
Variable AccessControlUpgradeable.__gap (@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#260) is not in mixedCase
Function OwnableUpgradeable.__Ownable_init() (@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol#29-31) is not in mixedCase
Function OwnableUpgradeable.__Ownable_init_unchained() (@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol#33-35) is not in mixedCase
Variable OwnableUpgradeable.__gap (@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol#94) is not in mixedCase
Function ERC1155Upgradeable.__ERC1155_init(string) (@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#36-38) is not in mixedCase
Function ERC1155Upgradeable.__ERC1155_init_unchained(string) (@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#40-42) is not in mixedCase
Variable ERC1155Upgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#508) is not in mixedCase
Function ERC1155BurnableUpgradeable.__ERC1155Burnable_init() (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol#16-17) is not in mixedCase
Function ERC1155BurnableUpgradeable.__ERC1155Burnable_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol#19-20) is not in mixedCase
Variable ERC1155BurnableUpgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol#44) is not in mixedCase
Function ERC1155ReceiverUpgradeable.__ERC1155Receiver_init() (@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol#14-15) is not in mixedCase
Function ERC1155ReceiverUpgradeable.__ERC1155Receiver_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol#17-18) is not in mixedCase
Variable ERC1155ReceiverUpgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol#31) is not in mixedCase
Function ERC20Upgradeable.__ERC20_init(string,string) (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#55-57) is not in mixedCase
Function ERC20Upgradeable.__ERC20_init_unchained(string,string) (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#59-62) is not in mixedCase
Variable ERC20Upgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol#376) is not in mixedCase
Function ERC20BurnableUpgradeable.__ERC20Burnable_init() (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol#16-17) is not in mixedCase
Function ERC20BurnableUpgradeable.__ERC20Burnable_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol#19-20) is not in mixedCase
Variable ERC20BurnableUpgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol#51) is not in mixedCase
Function IERC20PermitUpgradeable.DOMAIN_SEPARATOR() (@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol#89) is not in mixedCase
Function ERC721Upgradeable.__ERC721_init(string,string) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#45-47) is not in mixedCase
Function ERC721Upgradeable.__ERC721_init_unchained(string,string) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#49-52) is not in mixedCase
Function ERC721Upgradeable.__unsafe_increaseBalance(address,uint256) (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#468-470) is not in mixedCase
Variable ERC721Upgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol#477) is not in mixedCase
Function ERC721BurnableUpgradeable.__ERC721Burnable_init() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol#15-16) is not in mixedCase
Function ERC721BurnableUpgradeable.__ERC721Burnable_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol#18-19) is not in mixedCase
Variable ERC721BurnableUpgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol#38) is not in mixedCase
Function ERC721URIStorageUpgradeable.__ERC721URIStorage_init() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#19-20) is not in mixedCase
Function ERC721URIStorageUpgradeable.__ERC721URIStorage_init_unchained() (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#22-23) is not in mixedCase
Variable ERC721URIStorageUpgradeable.__gap (@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol#86) is not in mixedCase
Function ContextUpgradeable.__Context_init() (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#18-19) is not in mixedCase
Function ContextUpgradeable.__Context_init_unchained() (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#21-22) is not in mixedCase
Variable ContextUpgradeable.__gap (@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#40) is not in mixedCase
Function ERC165Upgradeable.__ERC165_init() (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#24-25) is not in mixedCase
Function ERC165Upgradeable.__ERC165_init_unchained() (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#27-28) is not in mixedCase
Variable ERC165Upgradeable.__gap (@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#41) is not in mixedCase
Parameter SafeMock.getTransactionHash(address,uint256,bytes,ISafeMock.Operation,uint256,uint256,uint256,address,address,uint256)._nonce (contracts/test/SafeMock.sol#135) is not in mixedCase
Function ERC1155ReceiverUpgradeableWithoutGap.__ERC1155Receiver_init() (contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol#28-31) is not in mixedCase
Function ERC1155ReceiverUpgradeableWithoutGap.__ERC1155Receiver_init_unchained() (contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol#34-35) is not in mixedCase
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions
KeyStorageMock.hello (contracts/test/KeyStorageMock.sol#38) should be constant
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant
ContractManager.owner (contracts/test/TestContractManager.sol#37) should be immutable
ERC20WithoutTransfer._decimals (contracts/test/erc20/ERC20WithoutTransfer.sol#30) should be immutable
FallbackEthTester.communityPool (contracts/test/FallbackEthTester.sol#38) should be immutable
FallbackEthTester.depositBoxEth (contracts/test/FallbackEthTester.sol#37) should be immutable
SkaleManagerMock.contractManager (contracts/test/SkaleManagerMock.sol#31) should be immutable
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable
. analyzed (163 contracts with 100 detectors), 198 result(s) found
{
"solc": {
"status": "ok",
"use_rc": 0,
"version": "0.8.27",
"strategy": "solc-select",
"solc_path": "/var/www/tripwire/.venv/bin/solc",
"install_rc": 0,
"use_stderr": null,
"use_stdout": "Switched global version to 0.8.27",
"install_stderr": null,
"install_stdout": "Version '0.8.27' is already installed, skipping..."
},
"solc_args": "--base-path /tmp/slither-3rzqsamt --include-path /tmp/slither-3rzqsamt/lib --include-path /tmp/slither-3rzqsamt/lib/openzeppelin-contracts --allow-paths /tmp/slither-3rzqsamt,/tmp/slither-3rzqsamt/lib,/tmp/slither-3rzqsamt/lib/openzeppelin-contracts,/tmp/slither-3rzqsamt/src",
"remappings": [
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"source_files": [
"@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/interfaces/IERC4906Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/interfaces/IERC721Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/structs/DoubleEndedQueueUpgradeable.sol",
"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol",
"@skalenetwork/etherbase-interfaces/IEtherbase.sol",
"@skalenetwork/etherbase-interfaces/IEtherbaseUpgradeable.sol",
"@skalenetwork/ima-interfaces/DomainTypes.sol",
"@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataMainnet.sol",
"@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataSchain.sol",
"@skalenetwork/ima-interfaces/IGasReimbursable.sol",
"@skalenetwork/ima-interfaces/IMessageListener.sol",
"@skalenetwork/ima-interfaces/IMessageProxy.sol",
"@skalenetwork/ima-interfaces/IMessageReceiver.sol",
"@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC1155.sol",
"@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC20.sol",
"@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxERC721.sol",
"@skalenetwork/ima-interfaces/mainnet/DepositBoxes/IDepositBoxEth.sol",
"@skalenetwork/ima-interfaces/mainnet/ICommunityPool.sol",
"@skalenetwork/ima-interfaces/mainnet/IDepositBox.sol",
"@skalenetwork/ima-interfaces/mainnet/ILinker.sol",
"@skalenetwork/ima-interfaces/mainnet/IMessageProxyForMainnet.sol",
"@skalenetwork/ima-interfaces/mainnet/ISkaleManagerClient.sol",
"@skalenetwork/ima-interfaces/mainnet/ITwin.sol",
"@skalenetwork/ima-interfaces/schain/bls/IFieldOperations.sol",
"@skalenetwork/ima-interfaces/schain/ICommunityLocker.sol",
"@skalenetwork/ima-interfaces/schain/IKeyStorage.sol",
"@skalenetwork/ima-interfaces/schain/IMessageProxyForSchain.sol",
"@skalenetwork/ima-interfaces/schain/ITokenManager.sol",
"@skalenetwork/ima-interfaces/schain/ITokenManagerLinker.sol",
"@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenContractManager.sol",
"@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC1155.sol",
"@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC20.sol",
"@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC721.sol",
"@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerEth.sol",
"@skalenetwork/ima-interfaces/schain/tokens/IERC1155OnChain.sol",
"@skalenetwork/ima-interfaces/schain/tokens/IERC20OnChain.sol",
"@skalenetwork/ima-interfaces/schain/tokens/IERC721OnChain.sol",
"@skalenetwork/ima-interfaces/schain/tokens/IEthErc20.sol",
"@skalenetwork/skale-manager-interfaces/IContractManager.sol",
"@skalenetwork/skale-manager-interfaces/INodes.sol",
"@skalenetwork/skale-manager-interfaces/ISchains.sol",
"@skalenetwork/skale-manager-interfaces/ISchainsInternal.sol",
"@skalenetwork/skale-manager-interfaces/IWallets.sol",
"@skalenetwork/skale-manager-interfaces/utils/IRandom.sol",
"contracts/extensions/ERC721ReferenceMintAndMetadataMainnet.sol",
"contracts/extensions/ERC721ReferenceMintAndMetadataSchain.sol",
"contracts/extensions/interfaces/MessageProxyClient.sol",
"contracts/extensions/interfaces/MessageReceiver.sol",
"contracts/extensions/interfaces/MessageSender.sol",
"contracts/mainnet/CommunityPool.sol",
"contracts/mainnet/DepositBox.sol",
"contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol",
"contracts/mainnet/DepositBoxes/DepositBoxERC721.sol",
"contracts/mainnet/DepositBoxes/DepositBoxERC721WithMetadata.sol",
"contracts/mainnet/DepositBoxes/DepositBoxEth.sol",
"contracts/mainnet/Linker.sol",
"contracts/mainnet/MessageProxyForMainnet.sol",
"contracts/mainnet/SkaleManagerClient.sol",
"contracts/mainnet/Twin.sol",
"contracts/MessageProxy.sol",
"contracts/Messages.sol",
"contracts/schain/bls/FieldOperations.sol",
"contracts/schain/bls/Precompiled.sol",
"contracts/schain/bls/SkaleVerifier.sol",
"contracts/schain/CommunityLocker.sol",
"contracts/schain/DefaultAddresses.sol",
"contracts/schain/KeyStorage.sol",
"contracts/schain/MessageProxyForSchain.sol",
"contracts/schain/TokenManager.sol",
"contracts/schain/TokenManagerLinker.sol",
"contracts/schain/TokenManagers/TokenManagerERC1155.sol",
"contracts/schain/TokenManagers/TokenManagerERC20.sol",
"contracts/schain/TokenManagers/TokenManagerERC721.sol",
"contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol",
"contracts/schain/TokenManagers/TokenManagerEth.sol",
"contracts/schain/tokens/ERC1155OnChain.sol",
"contracts/schain/tokens/ERC20OnChain.sol",
"contracts/schain/tokens/ERC721OnChain.sol",
"contracts/schain/tokens/EthErc20.sol",
"contracts/test/ConfigReader.sol",
"contracts/test/erc20/ERC20IncorrectTransfer.sol",
"contracts/test/erc20/ERC20TransferWithFalseReturn.sol",
"contracts/test/erc20/ERC20TransferWithoutReturn.sol",
"contracts/test/erc20/ERC20WithoutTransfer.sol",
"contracts/test/erc20/RevertableERC20.sol",
"contracts/test/EtherbaseMock.sol",
"contracts/test/FallbackEthTester.sol",
"contracts/test/KeyStorageMock.sol",
"contracts/test/Logger.sol",
"contracts/test/MessageProxyCaller.sol",
"contracts/test/MessageProxyForMainnetTester.sol",
"contracts/test/MessageProxyForSchainTester.sol",
"contracts/test/MessageProxyForSchainWithoutSignature.sol",
"contracts/test/MessagesTester.sol",
"contracts/test/PrecompiledMock.sol",
"contracts/test/ReceiverGasLimitMainnetMock.sol",
"contracts/test/ReceiverGasLimitSchainMock.sol",
"contracts/test/ReceiverMock.sol",
"contracts/test/SafeMock.sol",
"contracts/test/SkaleManagerMock.sol",
"contracts/test/SkaleVerifierMock.sol",
"contracts/test/TestCallReceiverContract.sol",
"contracts/test/TestContractManager.sol",
"contracts/test/TestNodes.sol",
"contracts/test/TestSchains.sol",
"contracts/test/TestSchainsInternal.sol",
"contracts/test/TestWallets.sol",
"contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol"
],
"contract_count": 0,
"contract_names": [],
"detector_count": 198,
"workspace_hash": "10d3067194bafc5f567da894ac1c65d33341c2e092cfbe71cce831784955701d",
"duration_seconds": 15.020244359970093,
"solc_version_requested": "0.8.27"
}
{"no_findings":false,"summary":"Found a high-severity ERC20 accounting break on lock, a medium-severity delayed-withdrawal claim-loss bug, and a low-severity unauthenticated oracle setter.","findings":[{"severity":"high","category":"other","title":"ERC20 bridge accounting trusts the requested amount instead of the amount actually received","exploit_scenario":"A user bridges a fee-on-transfer or deflationary ERC20. `DepositBoxERC20` records and messages the full `amount` before/without checking how many tokens the bridge actually received. The destination chain credits the full amount, but the source bridge locked less. The attacker can later exit the full credited balance and drain other users' liquidity or leave the bridge permanently undercollateralized. The same nominal-amount assumption exists in the schain-native ERC20 path when a token is locked for schain-to-schain transfer.","recommendation":"Measure `balanceBefore`/`balanceAfter` around every ERC20 pull and bridge only the actual received amount. Revert if the received amount is smaller than requested unless the token type is explicitly unsupported. Apply the same balance-delta accounting anywhere ERC20s are locked rather than burned.","evidence":"On mainnet, the code builds the outbound message and increments `transferredAmount` using the caller-supplied `amount`, then performs `safeTransferFrom` with no balance-delta check. On schain-native ERC20 transfers, `_saveTransferredAmount(..., amount)` is also done before `transferFrom`, again assuming the nominal amount was received.","locations":["contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:698","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:704","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:705","contracts/schain/TokenManagers/TokenManagerERC20.sol:339","contracts/schain/TokenManagers/TokenManagerERC20.sol:348","contracts/schain/TokenManagers/TokenManagerERC20.sol:350"]},{"severity":"medium","category":"other","title":"Delayed ERC20 withdrawals clear user claims before confirming token delivery","exploit_scenario":"When a delayed transfer becomes withdrawable, `retrieveFor` marks it completed or deletes it from the queue before attempting the ERC20 transfer. If the token transfer then fails, the call is swallowed and only `TransferSkipped` is emitted. A token admin can pause or blacklist transfers right before unlock, or a nonstandard token can fail transfer, causing the receiver's claim to be irreversibly erased while the tokens remain stuck in the bridge contract.","recommendation":"Do not mutate delayed-transfer state until the token transfer succeeds. Revert failed payouts, or leave the transfer pending so the user can retry later. If partial progress is needed, persist an explicit failed state with an admin/user recovery path instead of deleting the claim.","evidence":"`retrieveFor` removes or marks transfers as `COMPLETED` before calling `_doNTransfers`. `_doNTransfers` catches transfer failures and only emits `TransferSkipped`, without restoring the queue entry or status.","locations":["contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:631","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:635","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:651","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:734","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:737"]},{"severity":"low","category":"oracle","title":"`CommunityLocker.setGasPrice` accepts arbitrary caller-supplied oracle values","exploit_scenario":"Any account can update `mainnetGasPrice` and `gasPriceTimestamp` by calling `setGasPrice`; the signature parameter is unused and the verification check is commented out. Today this state is not consumed elsewhere in first-party code, so impact is limited, but if operators or future upgrades rely on it, an attacker can feed arbitrary prices and timestamps.","recommendation":"Require a verified signature or strict role-based authorization before updating oracle state. If the oracle is not live yet, disable the entrypoint rather than accepting unauthenticated writes.","evidence":"The function has no access-control modifier, the signature argument is unnamed/unused, and the intended `messageProxy.verifySignature(...)` check is commented out.","locations":["contracts/schain/CommunityLocker.sol:252","contracts/schain/CommunityLocker.sol:257","contracts/schain/CommunityLocker.sol:262","contracts/schain/CommunityLocker.sol:272"]}]}
ame);
}
connected = connected && messageProxy.isConnectedChain(schainName);
}
}
exec
/bin/bash -lc "sed -n '1,340p' contracts/schain/CommunityLocker.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/*
CommunityLocker.sol - SKALE Manager
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaiev
@author Artem Payvin
@author Vadim Yavorsky
SKALE Manager is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/ICommunityLocker.sol";
import "../Messages.sol";
interface ICommunityLockerInitializer is ICommunityLocker {
function initializeTimestamp() external;
}
/**
* @title CommunityLocker
* @dev Contract contains logic to perform automatic reimbursement
* of gas fees for sent messages
*/
contract CommunityLocker is ICommunityLockerInitializer, AccessControlEnumerableUpgradeable {
/**
* @dev Mainnet identifier.
*/
string constant public MAINNET_NAME = "Mainnet";
/**
* @dev Keccak256 hash of mainnet name.
*/
SchainHash constant public MAINNET_HASH = SchainHash.wrap(keccak256(abi.encodePacked(MAINNET_NAME)));
/**
* @dev id of a role that allows changing of the contract parameters.
*/
bytes32 public constant CONSTANT_SETTER_ROLE = keccak256("CONSTANT_SETTER_ROLE");
/**
* @dev Address of MessageProxyForSchain.
*/
IMessageProxyForSchain public messageProxy;
/**
* @dev Address of TokenManagerLinker.
*/
ITokenManagerLinker public tokenManagerLinker;
/**
* @dev Address of CommunityPool on mainnet.
*/
address public communityPool;
/**
* @dev Keccak256 hash of schain name.
*/
/// @custom:oz-retyped-from bytes32
SchainHash public schainHash;
// Disable slither check due to variable depreciation
// and unavailability of making it constant because
// it breaks upgradeability pattern.
// slither-disable-next-line constable-states
uint private _deprecatedTimeLimitPerMessage;
/**
* @dev Mapping of users who are allowed to send a message.
*/
// user address => allowed to send message
mapping(address => bool) public activeUsers;
/**
* @dev Timestamp of previous sent message by user.
*/
// user address => timestamp of last message
mapping(address => uint) public lastMessageTimeStamp;
/**
* @dev mainnet gas price(baseFee) value
*/
uint256 public mainnetGasPrice;
/**
* @dev Timestamp of previous set of mainnet gas price
*/
uint256 public gasPriceTimestamp;
/**
* @dev Amount of seconds after message sending
* when next message cannot be sent.
*/
// schainHash => time limit
/// @custom:oz-retyped-from mapping(bytes32 => uint256)
mapping(SchainHash => uint) public timeLimitPerMessage;
/**
* @dev Timestamp of previous sent message by user during
* schain to schain transfers
*/
// schainHash => user => timestamp
/// @custom:oz-retyped-from mapping(bytes32 => mapping(address => uint256))
mapping(SchainHash => mapping(address => uint)) public lastMessageTimeStampToSchain;
/**
* @dev Emitted when a user becomes active.
*/
event ActivateUser(
SchainHash schainHash,
address user
);
/**
* @dev Emitted when a user stops being active.
*/
event LockUser(
SchainHash schainHash,
address user
);
/**
* @dev Emitted when constants updated.
*/
event ConstantUpdated(
bytes32 indexed constantHash,
uint previousValue,
uint newValue
);
modifier checkUserBeforeTransfer(SchainHash chainHash, address user) {
uint256 lastTimestamp = lastMessageTimeStampToSchain[chainHash][user];
if (chainHash == MAINNET_HASH) {
require(activeUsers[user], "Recipient must be active");
lastTimestamp = lastMessageTimeStamp[user];
}
require(
lastTimestamp + timeLimitPerMessage[chainHash] < block.timestamp,
"Exceeded message rate limit"
);
_;
}
/**
* @dev Allows MessageProxy to post operational message from mainnet
* or SKALE chains.
*
* Requirements:
*
* - MessageProxy must be the caller of the function.
* - CommunityPool must be an origin of the message on mainnet.
* - The message must come from the mainnet.
* - The message must contains status of a user.
* - Status of a user in the message must be different from the current status.
*/
function postMessage(
SchainHash fromChainHash,
address sender,
bytes calldata data
)
external
override
{
require(msg.sender == address(messageProxy), "Sender is not a message proxy");
require(sender == communityPool, "Sender must be CommunityPool");
require(fromChainHash == MAINNET_HASH, "Source chain name must be Mainnet");
Messages.MessageType operation = Messages.getMessageType(data);
require(operation == Messages.MessageType.USER_STATUS, "The message should contain a status of user");
Messages.UserStatusMessage memory message = Messages.decodeUserStatusMessage(data);
require(activeUsers[message.receiver] != message.isActive, "Active user statuses must be different");
activeUsers[message.receiver] = message.isActive;
if (message.isActive) {
emit ActivateUser(schainHash, message.receiver);
} else {
emit LockUser(schainHash, message.receiver);
}
}
/**
* @dev Reverts if {receiver} is not allowed to send a message.
*
* Requirements:
*
* - Function caller has to be registered in TokenManagerLinker as a TokenManager.
* - {receiver} must be an active user.
* - Previous message sent by {receiver} must be sent earlier then {timeLimitPerMessage} seconds before current time
* or there are no messages sent by {receiver}.
*/
function checkAllowedToSendMessage(SchainHash chainHash, address receiver)
external
checkUserBeforeTransfer(chainHash, receiver)
override
{
require(
tokenManagerLinker.hasTokenManager(msg.sender),
"Sender is not registered token manager"
);
if (chainHash == MAINNET_HASH) {
lastMessageTimeStamp[receiver] = block.timestamp;
} else {
lastMessageTimeStampToSchain[chainHash][receiver] = block.timestamp;
}
}
/**
* @dev Set value of {timeLimitPerMessage} of given chain.
*
* Requirements:
*
* - Function caller has to be granted with {CONSTANT_SETTER_ROLE}.
*
* Emits a {ConstantUpdated} event.
*/
function setTimeLimitPerMessage(string memory chainName, uint newTimeLimitPerMessage) external override {
require(hasRole(CONSTANT_SETTER_ROLE, msg.sender), "Not enough permissions to set constant");
SchainHash chainHash = SchainHash.wrap(keccak256(abi.encodePacked(chainName)));
require(chainHash != schainHash, "Incorrect chain");
emit ConstantUpdated(
keccak256(abi.encodePacked("TimeLimitPerMessage")),
timeLimitPerMessage[chainHash],
newTimeLimitPerMessage
);
timeLimitPerMessage[chainHash] = newTimeLimitPerMessage;
}
/**
* @dev Set value of {mainnetGasPrice}.
*
* Requirements:
*
* - Signature should be verified.
*
* Emits a {ConstantUpdated} event.
*/
function setGasPrice(
uint gasPrice,
uint timestamp,
IMessageProxyForSchain.Signature memory
)
external
override
{
require(timestamp > gasPriceTimestamp, "Gas price timestamp already updated");
require(timestamp <= block.timestamp, "Timestamp should not be in the future");
// TODO: uncomment when oracle finished
// require(
// messageProxy.verifySignature(keccak256(abi.encodePacked(gasPrice, timestamp)), signature),
// "Signature is not verified"
// );
emit ConstantUpdated(
keccak256(abi.encodePacked("MainnetGasPrice")),
mainnetGasPrice,
gasPrice
);
mainnetGasPrice = gasPrice;
gasPriceTimestamp = timestamp;
}
/**
* @dev Is called once during contract deployment.
*/
function initialize(
string memory newSchainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newTokenManagerLinker,
address newCommunityPool
)
external
override
initializer
{
require(newCommunityPool != address(0), "Node address has to be set");
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init();
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
messageProxy = newMessageProxy;
tokenManagerLinker = newTokenManagerLinker;
schainHash = SchainHash.wrap(keccak256(abi.encodePacked(newSchainName)));
timeLimitPerMessage[MAINNET_HASH] = 5 minutes;
communityPool = newCommunityPool;
}
/**
* @dev Initialize timestamp after upgrade and should be removed after upgrade
*
* Requirements:
* Should be called only by address which hold DEFAULT_ADMIN_ROLE role
*/
function initializeTimestamp() external override {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Incorrect sender");
// Disable slither check due to moving data to the new data structure
// slither-disable-next-line uninitialized-state
timeLimitPerMessage[MAINNET_HASH] = _deprecatedTimeLimitPerMessage;
delete _deprecatedTimeLimitPerMessage;
}
}
exec
/bin/bash -lc "sed -n '1,160p' contracts/schain/DefaultAddresses.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* DefaultAddresses.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2022-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
library DefaultAddresses {
// 17 0x00 bytes
address public constant ETHERBASE = address(0xd2bA3e << (17 * 8));
// 16 0x00 bytes
address public constant TOKEN_MANAGER_LINKER = address(0xD2aAA008 << (16 * 8));
}
exec
/bin/bash -lc "sed -n '1,180p' contracts/schain/KeyStorage.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* MessageProxyForSchain.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/IKeyStorage.sol";
import "./bls/FieldOperations.sol";
/**
* @title KeyStorage
* @dev Holds common BLS public key.
*/
contract KeyStorage is IKeyStorage, AccessControlEnumerableUpgradeable {
uint256 public constant FREE_MEM_PTR = 0x40;
/**
* @dev Address of custom precompiled contract on SKALE chain
* to get uin256 value from the config.
*/
uint256 public constant FN_NUM_GET_CONFIG_VARIABLE_UINT256 = 0x13;
/**
* @dev Address of custom precompiled contract on SKALE chain
* to get current BLS public key.
*/
uint256 public constant FN_NUM_GET_CURRENT_BLS_PUBLIC_KEY = 0x19;
/**
* @dev Is called once during contract deployment.
*/
function initialize()
external
override
initializer
{
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init();
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/**
* @dev Get BLS common public key.
*/
function getBlsCommonPublicKey() external view override virtual returns (IFieldOperations.G2Point memory) {
return _getCurrentBLSPublicKey();
}
// private
/**
* @dev Get uint256 value from the skaled config.
*/
function _getConfigVariableUint256(
string memory strConfigVariableName
)
private
view
returns ( uint256 rv )
{
uint256 fmp = FREE_MEM_PTR;
uint256 blocks = (bytes(strConfigVariableName).length + 31) / 32 + 1;
bool success;
// solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(fmp)
for { let i := 0 } lt( i, blocks ) { i := add(1, i) } {
let where := add(ptr, mul(32, i))
let what := mload(add(strConfigVariableName, mul(32, i)))
mstore(where, what)
}
success := staticcall(not(0), FN_NUM_GET_CONFIG_VARIABLE_UINT256, ptr, mul( blocks, 32 ), ptr, 32)
rv := mload(ptr)
}
require(success, "Get config uint256 failed");
}
/**
* @dev Get current BLS public key the skaled.
*/
function _getCurrentBLSPublicKey()
private
view
returns ( IFieldOperations.G2Point memory pk )
{
uint256 fmp = FREE_MEM_PTR;
bool success;
uint xa;
uint xb;
uint ya;
uint yb;
// solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(fmp)
success := staticcall(not(0), FN_NUM_GET_CURRENT_BLS_PUBLIC_KEY, ptr, 0, ptr, 128)
xa := mload(ptr)
xb := mload(add(ptr, 32))
ya := mload(add(ptr, 64))
yb := mload(add(ptr, 96))
}
pk.x.a = xa;
pk.x.b = xb;
pk.y.a = ya;
pk.y.b = yb;
require(success, "Get current BLS public key failed");
}
}
exec
/bin/bash -lc "rg -n \"mainnetGasPrice|gasPriceTimestamp|setGasPrice\\(\" contracts -g '"'!contracts/test/**'"'" in /tmp/codex-sryvig8b
succeeded in 0ms:
contracts/schain/CommunityLocker.sol:100: uint256 public mainnetGasPrice;
contracts/schain/CommunityLocker.sol:105: uint256 public gasPriceTimestamp;
contracts/schain/CommunityLocker.sol:244: * @dev Set value of {mainnetGasPrice}.
contracts/schain/CommunityLocker.sol:252: function setGasPrice(
contracts/schain/CommunityLocker.sol:260: require(timestamp > gasPriceTimestamp, "Gas price timestamp already updated");
contracts/schain/CommunityLocker.sol:269: mainnetGasPrice,
contracts/schain/CommunityLocker.sol:272: mainnetGasPrice = gasPrice;
contracts/schain/CommunityLocker.sol:273: gasPriceTimestamp = timestamp;
exec
/bin/bash -lc "sed -n '1,260p' contracts/schain/TokenManagers/TokenManagerERC20.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* TokenManager.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2019-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
// cspell:words IERC20Upgradeable
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC20.sol";
import {SchainHash} from "@skalenetwork/ima-interfaces/DomainTypes.sol";
import "../../Messages.sol";
import "../tokens/ERC20OnChain.sol";
import "../TokenManager.sol";
/**
* @title TokenManagerERC20
* @dev Runs on SKALE Chains,
* accepts messages from mainnet,
* and creates ERC20 clones.
* TokenManagerERC20 mints tokens. When a user exits a SKALE chain, it burns them.
*/
contract TokenManagerERC20 is TokenManager, ITokenManagerERC20 {
using AddressUpgradeable for address;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
// address of ERC20 on Mainnet => ERC20 on Schain
mapping(address => ERC20OnChain) public deprecatedClonesErc20;
// address of clone on schain => totalSupplyOnMainnet
mapping(IERC20Upgradeable => uint) public totalSupplyOnMainnet;
// address clone on schain => added or not
mapping(ERC20OnChain => bool) public addedClones;
/// @custom:oz-retyped-from mapping(bytes32 => mapping(address => contract ERC20OnChain))
mapping(SchainHash => mapping(address => ERC20OnChain)) public clonesErc20;
/// @custom:oz-retyped-from mapping(bytes32 => mapping(address => uint256))
mapping(SchainHash => mapping(address => uint256)) public transferredAmount;
/// @custom:oz-retyped-from mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)
mapping(SchainHash => EnumerableSetUpgradeable.AddressSet) private _schainToERC20;
/**
* @dev Emitted when schain owner register new ERC20 clone.
*/
event ERC20TokenAdded(
SchainHash indexed chainHash,
address indexed erc20OnMainChain,
address indexed erc20OnSchain
);
/**
* @dev Emitted when TokenManagerERC20 automatically deploys new ERC20 clone.
*/
event ERC20TokenCreated(
SchainHash indexed chainHash,
address indexed erc20OnMainChain,
address indexed erc20OnSchain
);
/**
* @dev Emitted when someone sends tokens from mainnet to schain.
*/
event ERC20TokenReceived(
SchainHash indexed chainHash,
address indexed erc20OnMainChain,
address indexed erc20OnSchain,
uint256 amount
);
/**
* @dev Emitted when token is received by TokenManager and is ready to be cloned
* or transferred on SKALE chain.
*/
event ERC20TokenReady(SchainHash indexed chainHash, address indexed contractOnMainnet, uint256 amount);
/**
* @dev Move tokens from schain to mainnet.
*
* {contractOnMainnet} tokens are burned on schain and unlocked on mainnet for {msg.sender} address.
*/
function exitToMainERC20(
address contractOnMainnet,
uint256 amount
)
external
override
{
communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender);
_exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, amount);
}
/**
* @dev Move tokens from schain to schain.
*
* {contractOnMainnet} tokens are burned on origin schain
* and are minted on {targetSchainName} schain for {msg.sender} address.
*/
function transferToSchainERC20(
string calldata targetSchainName,
address contractOnMainnet,
uint256 amount
)
external
override
{
transferToSchainERC20Direct(targetSchainName, contractOnMainnet, amount, msg.sender);
}
/**
* @dev Allows MessageProxy to post operational message from mainnet
* or SKALE chains.
*
* Requirements:
*
* - MessageProxy must be the sender.
* - `fromChainHash` must exist in TokenManager addresses.
*/
function postMessage(
SchainHash fromChainHash,
address sender,
bytes calldata data
)
external
override
onlyMessageProxy
checkReceiverChain(fromChainHash, sender)
{
Messages.MessageType operation = Messages.getMessageType(data);
address receiver = address(0);
if (
operation == Messages.MessageType.TRANSFER_ERC20 ||
operation == Messages.MessageType.TRANSFER_ERC20_AND_TOKEN_INFO ||
operation == Messages.MessageType.TRANSFER_ERC20_AND_TOTAL_SUPPLY
) {
receiver = _sendERC20(fromChainHash, data);
} else {
revert("MessageType is unknown");
}
}
/**
* @dev Allows Schain owner to register an ERC20 token clone in the TokenManager.
* Runs on destination chain.
*/
function addERC20TokenByOwner(
string calldata originChainName,
address erc20OnOriginChain,
address newErc20OnSchain
)
external
override
onlyTokenRegistrar
{
SchainHash originChainHash = SchainHash.wrap(keccak256(abi.encodePacked(originChainName)));
ERC20OnChain erc20OnSchain = clonesErc20[originChainHash][erc20OnOriginChain];
require(messageProxy.isConnectedChain(originChainName), "Chain is not connected");
require(newErc20OnSchain.isContract(), "Given address is not a contract");
require(ERC20OnChain(newErc20OnSchain).totalSupply() == 0, "Total supply of a new token is not zero");
if (address(erc20OnSchain) != address(0)) {
require(erc20OnSchain.totalSupply() == 0, "Total supply of a previous token is not zero");
}
require(!addedClones[ERC20OnChain(newErc20OnSchain)], "Clone was already added");
clonesErc20[originChainHash][erc20OnOriginChain] = ERC20OnChain(newErc20OnSchain);
addedClones[ERC20OnChain(newErc20OnSchain)] = true;
emit ERC20TokenAdded(originChainHash, erc20OnOriginChain, newErc20OnSchain);
}
/**
* @dev Is called once during contract deployment.
*/
function initialize(
string memory newChainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newIMALinker,
ICommunityLocker newCommunityLocker,
address newDepositBox
)
external
override
{
TokenManager.initializeTokenManager(
newChainName,
newMessageProxy,
newIMALinker,
newCommunityLocker,
newDepositBox
);
}
/**
* @dev Move tokens from schain to schain to specified receiver.
*
* {contractOnMainnet} tokens are burned on origin schain
* and are minted on {targetSchainName} schain for {receiver} address.
*/
function transferToSchainERC20Direct(
string calldata targetSchainName,
address contractOnMainnet,
uint256 amount,
address receiver
)
public
override
{
SchainHash targetSchainHash = SchainHash.wrap(keccak256(abi.encodePacked(targetSchainName)));
transferToSchainHashERC20Direct(targetSchainHash, contractOnMainnet, amount, receiver);
}
/**
* @dev Move tokens from schain to schain to specified receiver.
*
* {contractOnMainnet} tokens are burned on origin schain
* and are minted on {targetSchainHash} schain for {receiver} address.
*/
function transferToSchainHashERC20Direct(
SchainHash targetSchainHash,
address contractOnMainnet,
uint256 amount,
address receiver
)
public
override
onlySchainTarget(targetSchainHash, receiver)
{
communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender);
_exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, receiver, amount);
}
// private
/**
* @dev Allows TokenManager to send ERC20 tokens.
*
* Emits a {ERC20TokenCreated} event if token did not exist and was automatically deployed.
* Emits a {ERC20TokenReceived} event on success.
*/
exec
/bin/bash -lc "sed -n '261,520p' contracts/schain/TokenManagers/TokenManagerERC20.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
function _sendERC20(SchainHash fromChainHash, bytes calldata data) private returns (address) {
Messages.MessageType messageType = Messages.getMessageType(data);
(address receiver, address token, uint256 amount) = _decodeErc20Message(data);
ERC20OnChain contractOnSchain;
if (messageType != Messages.MessageType.TRANSFER_ERC20) {
uint256 totalSupply;
if (messageType == Messages.MessageType.TRANSFER_ERC20_AND_TOTAL_SUPPLY) {
Messages.TransferErc20AndTotalSupplyMessage memory message =
Messages.decodeTransferErc20AndTotalSupplyMessage(data);
totalSupply = message.totalSupply;
contractOnSchain = clonesErc20[fromChainHash][token];
} else {
Messages.TransferErc20AndTokenInfoMessage memory message =
Messages.decodeTransferErc20AndTokenInfoMessage(data);
totalSupply = message.totalSupply;
contractOnSchain = clonesErc20[fromChainHash][token];
if (address(contractOnSchain) == address(0)) {
require(automaticDeploy, "Automatic deploy is disabled");
contractOnSchain = new ERC20OnChain(message.tokenInfo.name, message.tokenInfo.symbol);
clonesErc20[fromChainHash][token] = contractOnSchain;
addedClones[contractOnSchain] = true;
emit ERC20TokenCreated(fromChainHash, token, address(contractOnSchain));
}
}
if (totalSupply != totalSupplyOnMainnet[contractOnSchain]) {
totalSupplyOnMainnet[contractOnSchain] = totalSupply;
}
bool noOverflow;
uint updatedTotalSupply;
(noOverflow, updatedTotalSupply) = SafeMathUpgradeable.tryAdd(contractOnSchain.totalSupply(), amount);
require(
noOverflow && updatedTotalSupply <= totalSupplyOnMainnet[contractOnSchain],
"Total supply exceeded"
);
contractOnSchain.mint(receiver, amount);
} else {
require(token.isContract() && _schainToERC20[fromChainHash].contains(token), "Incorrect main chain token");
require(ERC20Upgradeable(token).balanceOf(address(this)) >= amount, "Not enough money");
_removeTransferredAmount(fromChainHash, token, amount);
require(
ERC20Upgradeable(token).transfer(receiver, amount),
"Transfer was failed"
);
}
emit ERC20TokenReceived(fromChainHash, token, address(contractOnSchain), amount);
messageProxy.topUpReceiverBalance(payable(receiver));
return receiver;
}
/**
* @dev Burn tokens on schain and send message to unlock them on target chain.
*/
function _exit(
SchainHash chainHash,
address messageReceiver,
address contractOnMainChain,
address to,
uint256 amount
)
private
{
bool isMainChainToken;
ERC20OnChain contractOnSchain = clonesErc20[chainHash][contractOnMainChain];
if (address(contractOnSchain) == address(0)) {
contractOnSchain = ERC20OnChain(contractOnMainChain);
require(!addedClones[contractOnSchain], "Incorrect main chain token");
isMainChainToken = true;
}
require(address(contractOnSchain).isContract(), "No token clone on schain");
require(contractOnSchain.balanceOf(msg.sender) >= amount, "Insufficient funds");
require(
contractOnSchain.allowance(
msg.sender,
address(this)
) >= amount,
"Transfer is not approved by token holder"
);
bytes memory data = Messages.encodeTransferErc20Message(address(contractOnMainChain), to, amount);
if (isMainChainToken) {
require(chainHash != MAINNET_HASH, "Main chain token could not be transferred to Mainnet");
data = _receiveERC20(
chainHash,
address(contractOnSchain),
to,
amount
);
_saveTransferredAmount(chainHash, address(contractOnSchain), amount);
require(
contractOnSchain.transferFrom(msg.sender, address(this), amount),
"Transfer was failed"
);
} else {
require(
contractOnSchain.transferFrom(msg.sender, address(this), amount),
"Transfer was failed"
);
contractOnSchain.burn(amount);
}
messageProxy.postOutgoingMessage(
chainHash,
messageReceiver,
data
);
}
/**
* @dev Saves amount of tokens that was transferred to schain.
*/
function _saveTransferredAmount(SchainHash chainHash, address erc20Token, uint256 amount) private {
transferredAmount[chainHash][erc20Token] += amount;
}
/**
* @dev Removes amount of tokens that was transferred from schain.
*/
function _removeTransferredAmount(SchainHash chainHash, address erc20Token, uint256 amount) private {
transferredAmount[chainHash][erc20Token] -= amount;
}
/**
* @dev Allows DepositBoxERC20 to receive ERC20 tokens.
*
* Emits an {ERC20TokenReady} event.
*
* Requirements:
*
* - Amount must be less than or equal to the total supply of the ERC20 contract.
* - Whitelist should be turned off for auto adding tokens to DepositBoxERC20.
*/
function _receiveERC20(
SchainHash chainHash,
address erc20OnMainChain,
address to,
uint256 amount
)
private
returns (bytes memory data)
{
ERC20BurnableUpgradeable erc20 = ERC20BurnableUpgradeable(erc20OnMainChain);
uint256 totalSupply = erc20.totalSupply();
require(amount <= totalSupply, "Amount is incorrect");
bool isERC20AddedToSchain = _schainToERC20[chainHash].contains(erc20OnMainChain);
if (!isERC20AddedToSchain) {
_addERC20ForSchain(chainHash, erc20OnMainChain);
data = Messages.encodeTransferErc20AndTokenInfoMessage(
erc20OnMainChain,
to,
amount,
_getErc20TotalSupply(erc20),
_getErc20TokenInfo(erc20)
);
} else {
data = Messages.encodeTransferErc20AndTotalSupplyMessage(
erc20OnMainChain,
to,
amount,
_getErc20TotalSupply(erc20)
);
}
emit ERC20TokenReady(chainHash, erc20OnMainChain, amount);
}
/**
* @dev Adds an ERC20 token to DepositBoxERC20.
*
* Emits an {ERC20TokenAdded} event.
*
* Requirements:
*
* - Given address should be contract.
*/
function _addERC20ForSchain(SchainHash chainHash, address erc20OnMainChain) private {
require(erc20OnMainChain.isContract(), "Given address is not a contract");
require(!_schainToERC20[chainHash].contains(erc20OnMainChain), "ERC20 Token was already added");
_schainToERC20[chainHash].add(erc20OnMainChain);
emit ERC20TokenAdded(chainHash, erc20OnMainChain, address(0));
}
/**
* @dev Returns total supply of ERC20 token.
*/
function _getErc20TotalSupply(ERC20Upgradeable erc20Token) private view returns (uint256) {
return erc20Token.totalSupply();
}
/**
* @dev Returns info about ERC20 token such as token name, decimals, symbol.
*/
function _getErc20TokenInfo(ERC20Upgradeable erc20Token) private view returns (Messages.Erc20TokenInfo memory) {
return Messages.Erc20TokenInfo({
name: erc20Token.name(),
decimals: erc20Token.decimals(),
symbol: erc20Token.symbol()
});
}
/**
* @dev Decodes ERC20 transfer message depending on type of message.
*/
function _decodeErc20Message(bytes calldata data)
private
pure
returns (address, address, uint256)
{
Messages.MessageType messageType = Messages.getMessageType(data);
if (messageType == Messages.MessageType.TRANSFER_ERC20) {
Messages.TransferErc20Message memory message =
Messages.decodeTransferErc20Message(data);
return (
message.receiver,
message.token,
message.amount
);
} else if (messageType == Messages.MessageType.TRANSFER_ERC20_AND_TOTAL_SUPPLY) {
Messages.TransferErc20AndTotalSupplyMessage memory messageTotalSupply =
Messages.decodeTransferErc20AndTotalSupplyMessage(data);
return (
messageTotalSupply.baseErc20transfer.receiver,
messageTotalSupply.baseErc20transfer.token,
messageTotalSupply.baseErc20transfer.amount
);
} else {
Messages.TransferErc20AndTokenInfoMessage memory messageTokenInfo =
Messages.decodeTransferErc20AndTokenInfoMessage(data);
return (
messageTokenInfo.baseErc20transfer.receiver,
messageTokenInfo.baseErc20transfer.token,
messageTokenInfo.baseErc20transfer.amount
);
}
}
}
exec
/bin/bash -lc "sed -n '1,280p' contracts/schain/TokenManagers/TokenManagerEth.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* TokenManager.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2019-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import {SchainHash} from "@skalenetwork/ima-interfaces/DomainTypes.sol";
import "@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerEth.sol";
import "../../Messages.sol";
import "../TokenManager.sol";
/**
* @title TokenManagerEth
* @dev Runs on SKALE Chains and
* accepts messages from mainnet.
* TokenManagerEth mints EthErc20 tokens. When a user exits a SKALE chain, it burns them.
*/
contract TokenManagerEth is TokenManager, ITokenManagerEth {
IEthErc20 public ethErc20;
/// Create a new token manager
/**
* @dev Register EthErc20 token.
*/
function setEthErc20Address(IEthErc20 newEthErc20Address) external override {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not authorized caller");
require(ethErc20 != newEthErc20Address, "Must be new address");
ethErc20 = newEthErc20Address;
}
/**
* @dev Move ETH from schain to mainnet.
*
* EthErc20 tokens are burned on schain and ETH are unlocked on mainnet for {to} address.
*/
function exitToMain(uint256 amount) external override {
communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender);
_exit(MAINNET_HASH, depositBox, msg.sender, amount);
}
/**
* @dev Allows MessageProxy to post operational message from mainnet
* or SKALE chains.
*
* Requirements:
*
* - MessageProxy must be the sender.
* - `fromChainHash` must exist in TokenManager addresses.
*/
function postMessage(
SchainHash fromChainHash,
address sender,
bytes calldata data
)
external
override
onlyMessageProxy
checkReceiverChain(fromChainHash, sender)
{
Messages.TransferEthMessage memory decodedMessage = Messages.decodeTransferEthMessage(data);
address receiver = decodedMessage.receiver;
require(receiver != address(0), "Incorrect receiver");
ethErc20.mint(receiver, decodedMessage.amount);
messageProxy.topUpReceiverBalance(payable(receiver));
}
/**
* @dev Is called once during contract deployment.
*/
function initialize(
string memory newChainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newIMALinker,
ICommunityLocker newCommunityLocker,
address newDepositBox,
IEthErc20 ethErc20Address
)
external
override
initializer
{
TokenManager.initializeTokenManager(
newChainName,
newMessageProxy,
newIMALinker,
newCommunityLocker,
newDepositBox
);
ethErc20 = ethErc20Address;
}
// private
/**
* @dev Checks whether sender contract is DepositBox.
*/
function _checkSender(SchainHash fromChainHash, address sender) internal view override returns (bool) {
return fromChainHash == MAINNET_HASH && sender == depositBox;
}
/**
* @dev Burn EthErc20 tokens on schain and send message to unlock ETH on target chain.
*/
function _exit(
SchainHash chainHash,
address messageReceiver,
address to,
uint256 amount
)
private
{
if (amount > 0) {
ethErc20.forceBurn(msg.sender, amount);
}
bytes memory data = Messages.encodeTransferEthMessage(to, amount);
messageProxy.postOutgoingMessage(
chainHash,
messageReceiver,
data
);
}
}
exec
/bin/bash -lc "sed -n '1,420p' contracts/schain/TokenManagers/TokenManagerERC721.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* TokenManager.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2019-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC721.sol";
import "../../Messages.sol";
import "../tokens/ERC721OnChain.sol";
import "../TokenManager.sol";
/**
* @title TokenManagerERC721
* @dev Runs on SKALE Chains,
* accepts messages from mainnet,
* and creates ERC721 clones.
* TokenManagerERC721 mints tokens. When a user exits a SKALE chain, it burns them.
*/
contract TokenManagerERC721 is TokenManager, ITokenManagerERC721 {
using AddressUpgradeable for address;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
// address of ERC721 on Mainnet => ERC721 on Schain
mapping(address => ERC721OnChain) public deprecatedClonesErc721;
// address clone on schain => added or not
mapping(ERC721OnChain => bool) public addedClones;
/// @custom:oz-retyped-from mapping(bytes32 => mapping(address => contract ERC721OnChain))
mapping(SchainHash => mapping(address => ERC721OnChain)) public clonesErc721;
/// @custom:oz-retyped-from mapping(address => mapping(uint256 => bytes32))
mapping(address => mapping(uint256 => SchainHash)) public transferredAmount;
/// @custom:oz-retyped-from mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)
mapping(SchainHash => EnumerableSetUpgradeable.AddressSet) private _schainToERC721;
/**
* @dev Emitted when schain owner register new ERC721 clone.
*/
event ERC721TokenAdded(
SchainHash indexed chainHash,
address indexed erc721OnMainChain,
address indexed erc721OnSchain
);
/**
* @dev Emitted when TokenManagerERC721 automatically deploys new ERC721 clone.
*/
event ERC721TokenCreated(
SchainHash indexed chainHash,
address indexed erc721OnMainChain,
address indexed erc721OnSchain
);
/**
* @dev Emitted when someone sends tokens from mainnet to schain.
*/
event ERC721TokenReceived(
SchainHash indexed chainHash,
address indexed erc721OnMainChain,
address indexed erc721OnSchain,
uint256 tokenId
);
/**
* @dev Emitted when token is received by TokenManager and is ready to be cloned
* or transferred on SKALE chain.
*/
event ERC721TokenReady(SchainHash indexed chainHash, address indexed contractOnMainnet, uint256 tokenId);
/**
* @dev Move tokens from schain to mainnet.
*
* {contractOnMainnet} tokens are burned on schain and unlocked on mainnet for {msg.sender} address.
*/
function exitToMainERC721(
address contractOnMainnet,
uint256 tokenId
)
external
override
{
communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender);
_exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, tokenId);
}
/**
* @dev Move tokens from schain to schain.
*
* {contractOnMainnet} tokens are burned on origin schain
* and are minted on {targetSchainName} schain for {msg.sender} address.
*/
function transferToSchainERC721(
string calldata targetSchainName,
address contractOnMainnet,
uint256 tokenId
)
external
override
rightTransaction(targetSchainName, msg.sender)
{
SchainHash targetSchainHash = SchainHash.wrap(keccak256(abi.encodePacked(targetSchainName)));
communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender);
_exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, tokenId);
}
/**
* @dev Allows MessageProxy to post operational message from mainnet
* or SKALE chains.
*
* Requirements:
*
* - MessageProxy must be the sender.
* - `fromChainHash` must exist in TokenManager addresses.
*/
function postMessage(
SchainHash fromChainHash,
address sender,
bytes calldata data
)
external
virtual
override
onlyMessageProxy
checkReceiverChain(fromChainHash, sender)
{
Messages.MessageType operation = Messages.getMessageType(data);
address receiver = address(0);
if (
operation == Messages.MessageType.TRANSFER_ERC721_AND_TOKEN_INFO ||
operation == Messages.MessageType.TRANSFER_ERC721
) {
receiver = _sendERC721(fromChainHash, data);
} else {
revert("MessageType is unknown");
}
}
/**
* @dev Allows Schain owner to register an ERC721 token clone in the token manager.
*/
function addERC721TokenByOwner(
string calldata originChainName,
address erc721OnOriginChain,
address newErc721OnSchain
)
external
override
onlyTokenRegistrar
{
SchainHash originChainHash = SchainHash.wrap(keccak256(abi.encodePacked(originChainName)));
require(messageProxy.isConnectedChain(originChainName), "Chain is not connected");
require(newErc721OnSchain.isContract(), "Given address is not a contract");
require(address(clonesErc721[originChainHash][erc721OnOriginChain]) == address(0), "Could not relink clone");
require(!addedClones[ERC721OnChain(newErc721OnSchain)], "Clone was already added");
clonesErc721[originChainHash][erc721OnOriginChain] = ERC721OnChain(newErc721OnSchain);
addedClones[ERC721OnChain(newErc721OnSchain)] = true;
emit ERC721TokenAdded(originChainHash, erc721OnOriginChain, newErc721OnSchain);
}
/**
* @dev Is called once during contract deployment.
*/
function initialize(
string memory newChainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newIMALinker,
ICommunityLocker newCommunityLocker,
address newDepositBox
)
external
override
{
TokenManager.initializeTokenManager(
newChainName,
newMessageProxy,
newIMALinker,
newCommunityLocker,
newDepositBox
);
}
// private
/**
* @dev Allows TokenManager to send ERC721 tokens.
*
* Emits a {ERC20TokenCreated} event if token did not exist and was automatically deployed.
* Emits a {ERC20TokenReceived} event on success.
*/
function _sendERC721(SchainHash fromChainHash, bytes calldata data) internal virtual returns (address) {
Messages.MessageType messageType = Messages.getMessageType(data);
address receiver;
address token;
uint256 tokenId;
ERC721OnChain contractOnSchain;
if (messageType == Messages.MessageType.TRANSFER_ERC721) {
Messages.TransferErc721Message memory message = Messages.decodeTransferErc721Message(data);
receiver = message.receiver;
token = message.token;
tokenId = message.tokenId;
contractOnSchain = clonesErc721[fromChainHash][token];
} else {
Messages.TransferErc721AndTokenInfoMessage memory message =
Messages.decodeTransferErc721AndTokenInfoMessage(data);
receiver = message.baseErc721transfer.receiver;
token = message.baseErc721transfer.token;
tokenId = message.baseErc721transfer.tokenId;
contractOnSchain = clonesErc721[fromChainHash][token];
if (address(contractOnSchain) == address(0)) {
require(automaticDeploy, "Automatic deploy is disabled");
contractOnSchain = new ERC721OnChain(message.tokenInfo.name, message.tokenInfo.symbol);
clonesErc721[fromChainHash][token] = contractOnSchain;
addedClones[contractOnSchain] = true;
emit ERC721TokenCreated(fromChainHash, token, address(contractOnSchain));
}
}
if (
messageType == Messages.MessageType.TRANSFER_ERC721 &&
fromChainHash != MAINNET_HASH &&
_schainToERC721[fromChainHash].contains(token)
) {
require(token.isContract(), "Incorrect main chain token");
require(IERC721Upgradeable(token).ownerOf(tokenId) == address(this), "Incorrect tokenId");
_removeTransferredAmount(fromChainHash, token, tokenId);
IERC721Upgradeable(token).transferFrom(address(this), receiver, tokenId);
} else {
contractOnSchain.mint(receiver, tokenId);
}
emit ERC721TokenReceived(fromChainHash, token, address(contractOnSchain), tokenId);
messageProxy.topUpReceiverBalance(payable(receiver));
return receiver;
}
/**
* @dev Removes the ids of tokens that was transferred from schain.
*/
function _removeTransferredAmount(SchainHash chainHash, address erc721Token, uint256 tokenId) internal {
require(transferredAmount[erc721Token][tokenId] == chainHash, "Token was already transferred from chain");
transferredAmount[erc721Token][tokenId] = SchainHash.wrap(bytes32(0));
}
/**
* @dev Allows DepositBoxERC721 to receive ERC721 tokens.
*
* Emits an {ERC721TokenReady} event.
*
* Requirements:
*
* - Whitelist should be turned off for auto adding tokens to DepositBoxERC721.
*/
function _receiveERC721(
SchainHash chainHash,
address erc721OnMainChain,
address to,
uint256 tokenId
)
internal
virtual
returns (bytes memory data)
{
bool isERC721AddedToSchain = _schainToERC721[chainHash].contains(erc721OnMainChain);
if (!isERC721AddedToSchain) {
_addERC721ForSchain(chainHash, erc721OnMainChain);
data = Messages.encodeTransferErc721AndTokenInfoMessage(
erc721OnMainChain,
to,
tokenId,
_getTokenInfo(IERC721MetadataUpgradeable(erc721OnMainChain))
);
} else {
data = Messages.encodeTransferErc721Message(erc721OnMainChain, to, tokenId);
}
emit ERC721TokenReady(chainHash, erc721OnMainChain, tokenId);
}
/**
* @dev Adds an ERC721 token to DepositBoxERC721.
*
* Emits an {ERC721TokenAdded} event.
*
* Requirements:
*
* - Given address should be contract.
*/
function _addERC721ForSchain(SchainHash chainHash, address erc721OnMainChain) internal {
require(erc721OnMainChain.isContract(), "Given address is not a contract");
require(!_schainToERC721[chainHash].contains(erc721OnMainChain), "ERC721 Token was already added");
_schainToERC721[chainHash].add(erc721OnMainChain);
emit ERC721TokenAdded(chainHash, erc721OnMainChain, address(0));
}
/**
* @dev Burn tokens on schain and send message to unlock them on target chain.
*/
function _exit(
SchainHash chainHash,
address messageReceiver,
address contractOnMainChain,
address to,
uint256 tokenId
)
internal
virtual
{
bool isMainChainToken;
ERC721OnChain contractOnSchain = clonesErc721[chainHash][contractOnMainChain];
if (address(contractOnSchain) == address(0)) {
contractOnSchain = ERC721OnChain(contractOnMainChain);
require(!addedClones[contractOnSchain], "Incorrect main chain token");
isMainChainToken = true;
}
require(address(contractOnSchain).isContract(), "No token clone on schain");
require(contractOnSchain.getApproved(tokenId) == address(this), "Not allowed ERC721 Token");
bytes memory data = Messages.encodeTransferErc721Message(contractOnMainChain, to, tokenId);
if (isMainChainToken) {
require(chainHash != MAINNET_HASH, "Main chain token could not be transfered to Mainnet");
data = _receiveERC721(
chainHash,
address(contractOnSchain),
msg.sender,
tokenId
);
_saveTransferredAmount(chainHash, address(contractOnSchain), tokenId);
contractOnSchain.transferFrom(msg.sender, address(this), tokenId);
} else {
contractOnSchain.transferFrom(msg.sender, address(this), tokenId);
contractOnSchain.burn(tokenId);
}
messageProxy.postOutgoingMessage(chainHash, messageReceiver, data);
}
/**
* @dev Saves the ids of tokens that was transferred to schain.
*/
function _saveTransferredAmount(SchainHash chainHash, address erc721Token, uint256 tokenId) internal {
require(
transferredAmount[erc721Token][tokenId] == SchainHash.wrap(bytes32(0)),
"Token was already transferred to chain"
);
transferredAmount[erc721Token][tokenId] = chainHash;
}
/**
* @dev Returns info about ERC721 token such as token name, symbol.
*/
function _getTokenInfo(IERC721MetadataUpgradeable erc721) internal view returns (Messages.Erc721TokenInfo memory) {
return Messages.Erc721TokenInfo({
name: erc721.name(),
symbol: erc721.symbol()
});
}
function _isERC721AddedToSchain(SchainHash chainHash, address erc721OnMainChain) internal view returns (bool) {
return _schainToERC721[chainHash].contains(erc721OnMainChain);
}
}
exec
/bin/bash -lc "sed -n '1,260p' contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* TokenManagerERC721WithMetadata.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "./TokenManagerERC721.sol";
import "../../Messages.sol";
/**
* @title TokenManagerERC721WithMetadata
* @dev Runs on SKALE Chains,
* accepts messages from mainnet,
* and creates ERC721 clones.
* TokenManagerERC721 mints tokens. When a user exits a SKALE chain, it burns them.
*/
contract TokenManagerERC721WithMetadata is TokenManagerERC721 {
using AddressUpgradeable for address;
/**
* @dev Allows MessageProxy to post operational message from mainnet
* or SKALE chains.
*
* Requirements:
*
* - MessageProxy must be the sender.
* - `fromChainHash` must exist in TokenManager addresses.
*/
function postMessage(
SchainHash fromChainHash,
address sender,
bytes calldata data
)
external
override
onlyMessageProxy
checkReceiverChain(fromChainHash, sender)
{
Messages.MessageType operation = Messages.getMessageType(data);
address receiver = address(0);
if (
operation == Messages.MessageType.TRANSFER_ERC721_WITH_METADATA_AND_TOKEN_INFO ||
operation == Messages.MessageType.TRANSFER_ERC721_WITH_METADATA
) {
receiver = _sendERC721(fromChainHash, data);
} else {
revert("MessageType is unknown");
}
}
/**
* @dev Allows TokenManager to send ERC721 tokens.
*
* Emits a {ERC20TokenCreated} event if token did not exist and was automatically deployed.
* Emits a {ERC20TokenReceived} event on success.
*/
function _sendERC721(SchainHash fromChainHash, bytes calldata data) internal override returns (address) {
Messages.MessageType messageType = Messages.getMessageType(data);
address receiver;
address token;
uint256 tokenId;
string memory tokenURI;
ERC721OnChain contractOnSchain;
if (messageType == Messages.MessageType.TRANSFER_ERC721_WITH_METADATA) {
Messages.TransferErc721MessageWithMetadata memory message =
Messages.decodeTransferErc721MessageWithMetadata(data);
receiver = message.erc721message.receiver;
token = message.erc721message.token;
tokenId = message.erc721message.tokenId;
tokenURI = message.tokenURI;
contractOnSchain = clonesErc721[fromChainHash][token];
} else {
Messages.TransferErc721WithMetadataAndTokenInfoMessage memory message =
Messages.decodeTransferErc721WithMetadataAndTokenInfoMessage(data);
receiver = message.baseErc721transferWithMetadata.erc721message.receiver;
token = message.baseErc721transferWithMetadata.erc721message.token;
tokenId = message.baseErc721transferWithMetadata.erc721message.tokenId;
tokenURI = message.baseErc721transferWithMetadata.tokenURI;
contractOnSchain = clonesErc721[fromChainHash][token];
if (address(contractOnSchain) == address(0)) {
require(automaticDeploy, "Automatic deploy is disabled");
contractOnSchain = new ERC721OnChain(message.tokenInfo.name, message.tokenInfo.symbol);
clonesErc721[fromChainHash][token] = contractOnSchain;
addedClones[contractOnSchain] = true;
emit ERC721TokenCreated(fromChainHash, token, address(contractOnSchain));
}
}
if (
messageType == Messages.MessageType.TRANSFER_ERC721_WITH_METADATA &&
fromChainHash != MAINNET_HASH &&
_isERC721AddedToSchain(fromChainHash, token)
) {
require(token.isContract(), "Incorrect main chain token");
require(IERC721Upgradeable(token).ownerOf(tokenId) == address(this), "Incorrect tokenId");
_removeTransferredAmount(fromChainHash, token, tokenId);
IERC721Upgradeable(token).transferFrom(address(this), receiver, tokenId);
} else {
contractOnSchain.mint(receiver, tokenId);
contractOnSchain.setTokenURI(tokenId, tokenURI);
}
emit ERC721TokenReceived(fromChainHash, token, address(contractOnSchain), tokenId);
messageProxy.topUpReceiverBalance(payable(receiver));
return receiver;
}
/**
* @dev Burn tokens on schain and send message to unlock them on target chain.
*/
function _exit(
SchainHash chainHash,
address messageReceiver,
address contractOnMainChain,
address to,
uint256 tokenId
)
internal
override
{
bool isMainChainToken;
ERC721OnChain contractOnSchain = clonesErc721[chainHash][contractOnMainChain];
if (address(contractOnSchain) == address(0)) {
contractOnSchain = ERC721OnChain(contractOnMainChain);
require(!addedClones[contractOnSchain], "Incorrect main chain token");
isMainChainToken = true;
}
require(address(contractOnSchain).isContract(), "No token clone on schain");
require(contractOnSchain.getApproved(tokenId) == address(this), "Not allowed ERC721 Token");
bytes memory data = Messages.encodeTransferErc721MessageWithMetadata(
contractOnMainChain,
to,
tokenId,
_getTokenURI(IERC721MetadataUpgradeable(contractOnSchain), tokenId)
);
if (isMainChainToken) {
require(chainHash != MAINNET_HASH, "Main chain token could not be transfered to Mainnet");
data = _receiveERC721(
chainHash,
address(contractOnSchain),
msg.sender,
tokenId
);
_saveTransferredAmount(chainHash, address(contractOnSchain), tokenId);
contractOnSchain.transferFrom(msg.sender, address(this), tokenId);
} else {
contractOnSchain.transferFrom(msg.sender, address(this), tokenId);
contractOnSchain.burn(tokenId);
}
messageProxy.postOutgoingMessage(chainHash, messageReceiver, data);
}
/**
* @dev Allows DepositBoxERC721 to receive ERC721 tokens.
*
* Emits an {ERC721TokenReady} event.
*
* Requirements:
*
* - Whitelist should be turned off for auto adding tokens to DepositBoxERC721.
*/
function _receiveERC721(
SchainHash chainHash,
address erc721OnMainChain,
address to,
uint256 tokenId
)
internal
override
returns (bytes memory data)
{
bool isERC721AddedToSchain = _isERC721AddedToSchain(chainHash, erc721OnMainChain);
if (!isERC721AddedToSchain) {
_addERC721ForSchain(chainHash, erc721OnMainChain);
data = Messages.encodeTransferErc721WithMetadataAndTokenInfoMessage(
erc721OnMainChain,
to,
tokenId,
_getTokenURI(IERC721MetadataUpgradeable(erc721OnMainChain), tokenId),
_getTokenInfo(IERC721MetadataUpgradeable(erc721OnMainChain))
);
} else {
data = Messages.encodeTransferErc721MessageWithMetadata(
erc721OnMainChain,
to,
tokenId,
_getTokenURI(IERC721MetadataUpgradeable(erc721OnMainChain), tokenId)
);
}
emit ERC721TokenReady(chainHash, erc721OnMainChain, tokenId);
}
/**
* @dev Returns tokenURI of ERC721 token.
*/
function _getTokenURI(IERC721MetadataUpgradeable erc721, uint256 tokenId) private view returns (string memory) {
return erc721.tokenURI(tokenId);
}
}
exec
/bin/bash -lc "sed -n '1,700p' contracts/schain/TokenManagers/TokenManagerERC1155.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* TokenManager.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2019-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC1155.sol";
import "../../Messages.sol";
import "../tokens/ERC1155OnChain.sol";
import "../TokenManager.sol";
import "../../thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol";
/**
* @title TokenManagerERC1155
* @dev Runs on SKALE Chains,
* accepts messages from mainnet,
* and creates ERC1155 clones.
* TokenManagerERC1155 mints tokens. When a user exits a SKALE chain, it burns them.
*/
contract TokenManagerERC1155 is
TokenManager,
ERC1155ReceiverUpgradeableWithoutGap,
ITokenManagerERC1155
{
using AddressUpgradeable for address;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
// address of ERC1155 on Mainnet => ERC1155 on Schain
mapping(address => ERC1155OnChain) public deprecatedClonesErc1155;
// address clone on schain => added or not
mapping(ERC1155OnChain => bool) public addedClones;
/// @custom:oz-retyped-from mapping(bytes32 => mapping(address => contract ERC1155OnChain))
mapping(SchainHash => mapping(address => ERC1155OnChain)) public clonesErc1155;
/// @custom:oz-retyped-from mapping(bytes32 => mapping(address => mapping(uint256 => uint256)))
mapping(SchainHash => mapping(address => mapping(uint256 => uint256))) public transferredAmount;
/// @custom:oz-retyped-from mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)
mapping(SchainHash => EnumerableSetUpgradeable.AddressSet) private _schainToERC1155;
/**
* @dev Emitted when schain owner register new ERC1155 clone.
*/
event ERC1155TokenAdded(
SchainHash indexed chainHash,
address indexed erc1155OnMainnet,
address indexed erc1155OnSchain
);
/**
* @dev Emitted when TokenManagerERC1155 automatically deploys new ERC1155 clone.
*/
event ERC1155TokenCreated(
SchainHash indexed chainHash,
address indexed erc1155OnMainnet,
address indexed erc1155OnSchain
);
/**
* @dev Emitted when someone sends tokens from mainnet to schain.
*/
event ERC1155TokenReceived(
SchainHash indexed chainHash,
address indexed erc1155OnMainnet,
address indexed erc1155OnSchain,
uint256[] ids,
uint256[] amounts
);
/**
* @dev Emitted when token is received by TokenManager and is ready to be cloned
* or transferred on SKALE chain.
*/
event ERC1155TokenReady(
SchainHash indexed chainHash,
address indexed contractOnMainnet,
uint256[] ids,
uint256[] amounts
);
/**
* @dev Move tokens from schain to mainnet.
*
* {contractOnMainnet} tokens are burned on schain and unlocked on mainnet for {to} address.
*/
function exitToMainERC1155(
address contractOnMainnet,
uint256 id,
uint256 amount
)
external
override
{
communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender);
_exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, id, amount);
}
/**
* @dev Move batch of tokens from schain to mainnet.
*
* {contractOnMainnet} tokens are burned on schain and unlocked on mainnet for {to} address.
*/
function exitToMainERC1155Batch(
address contractOnMainnet,
uint256[] calldata ids,
uint256[] calldata amounts
)
external
override
{
communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender);
_exitBatch(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, ids, amounts);
}
/**
* @dev Move tokens from schain to schain.
*
* {contractOnMainnet} tokens are burned on origin schain
* and are minted on {targetSchainName} schain for {to} address.
*/
function transferToSchainERC1155(
string calldata targetSchainName,
address contractOnMainnet,
uint256 id,
uint256 amount
)
external
override
rightTransaction(targetSchainName, msg.sender)
{
SchainHash targetSchainHash = SchainHash.wrap(keccak256(abi.encodePacked(targetSchainName)));
communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender);
_exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, id, amount);
}
/**
* @dev Move batch of tokens from schain to schain.
*
* {contractOnMainnet} tokens are burned on origin schain
* and are minted on {targetSchainName} schain for {to} address.
*/
function transferToSchainERC1155Batch(
string calldata targetSchainName,
address contractOnMainnet,
uint256[] calldata ids,
uint256[] calldata amounts
)
external
override
rightTransaction(targetSchainName, msg.sender)
{
SchainHash targetSchainHash = SchainHash.wrap(keccak256(abi.encodePacked(targetSchainName)));
communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender);
_exitBatch(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, ids, amounts);
}
/**
* @dev Allows MessageProxy to post operational message from mainnet
* or SKALE chains.
*
* Requirements:
*
* - MessageProxy must be the sender.
* - `fromChainHash` must exist in TokenManagerERC1155 addresses.
*/
function postMessage(
SchainHash fromChainHash,
address sender,
bytes calldata data
)
external
override
onlyMessageProxy
checkReceiverChain(fromChainHash, sender)
{
Messages.MessageType operation = Messages.getMessageType(data);
address receiver = address(0);
if (
operation == Messages.MessageType.TRANSFER_ERC1155 ||
operation == Messages.MessageType.TRANSFER_ERC1155_AND_TOKEN_INFO
) {
receiver = _sendERC1155(fromChainHash, data);
} else if (
operation == Messages.MessageType.TRANSFER_ERC1155_BATCH ||
operation == Messages.MessageType.TRANSFER_ERC1155_BATCH_AND_TOKEN_INFO
) {
receiver = _sendERC1155Batch(fromChainHash, data);
} else {
revert("MessageType is unknown");
}
}
/**
* @dev Allows Schain owner to register an ERC1155 token clone in the token manager.
*/
function addERC1155TokenByOwner(
string calldata originChainName,
address erc1155OnOriginChain,
address newErc1155OnSchain
)
external
override
onlyTokenRegistrar
{
SchainHash originChainHash = SchainHash.wrap(keccak256(abi.encodePacked(originChainName)));
require(messageProxy.isConnectedChain(originChainName), "Chain is not connected");
require(newErc1155OnSchain.isContract(), "Given address is not a contract");
require(address(clonesErc1155[originChainHash][erc1155OnOriginChain]) == address(0), "Could not relink clone");
require(!addedClones[ERC1155OnChain(newErc1155OnSchain)], "Clone was already added");
clonesErc1155[originChainHash][erc1155OnOriginChain] = ERC1155OnChain(newErc1155OnSchain);
addedClones[ERC1155OnChain(newErc1155OnSchain)] = true;
emit ERC1155TokenAdded(originChainHash, erc1155OnOriginChain, newErc1155OnSchain);
}
/**
* @dev Is called once during contract deployment.
*/
function initialize(
string memory newChainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newIMALinker,
ICommunityLocker newCommunityLocker,
address newDepositBox
)
external
override
initializer
{
TokenManager.initializeTokenManager(
newChainName,
newMessageProxy,
newIMALinker,
newCommunityLocker,
newDepositBox
);
}
function onERC1155Received(
address operator,
address,
uint256,
uint256,
bytes calldata
)
external
view
override
returns(bytes4)
{
require(operator == address(this), "Revert ERC1155 transfer");
return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
}
function onERC1155BatchReceived(
address operator,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
)
external
view
override
returns(bytes4)
{
require(operator == address(this), "Revert ERC1155 batch transfer");
return bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"));
}
/**
* @dev Checks whether contract supports such interface (first 4 bytes of method name and its params).
*/
function supportsInterface(
bytes4 interfaceId
)
public
view
override(AccessControlEnumerableUpgradeable, ERC1155ReceiverUpgradeableWithoutGap)
returns (bool)
{
return interfaceId == type(TokenManager).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev Allows TokenManager to send ERC1155 tokens.
*
* Emits a {ERC20TokenCreated} event if token did not exist and was automatically deployed.
* Emits a {ERC20TokenReceived} event on success.
*/
function _sendERC1155(SchainHash fromChainHash, bytes calldata data) private returns (address) {
Messages.MessageType messageType = Messages.getMessageType(data);
address receiver;
address token;
uint256 id;
uint256 amount;
ERC1155OnChain contractOnSchain;
if (messageType == Messages.MessageType.TRANSFER_ERC1155){
Messages.TransferErc1155Message memory message = Messages.decodeTransferErc1155Message(data);
receiver = message.receiver;
token = message.token;
id = message.id;
amount = message.amount;
contractOnSchain = clonesErc1155[fromChainHash][token];
} else {
Messages.TransferErc1155AndTokenInfoMessage memory message =
Messages.decodeTransferErc1155AndTokenInfoMessage(data);
receiver = message.baseErc1155transfer.receiver;
token = message.baseErc1155transfer.token;
id = message.baseErc1155transfer.id;
amount = message.baseErc1155transfer.amount;
contractOnSchain = clonesErc1155[fromChainHash][token];
if (address(contractOnSchain) == address(0)) {
require(automaticDeploy, "Automatic deploy is disabled");
contractOnSchain = new ERC1155OnChain(message.tokenInfo.uri);
clonesErc1155[fromChainHash][token] = contractOnSchain;
addedClones[contractOnSchain] = true;
emit ERC1155TokenCreated(fromChainHash, token, address(contractOnSchain));
}
}
if (
messageType == Messages.MessageType.TRANSFER_ERC1155 &&
fromChainHash != MAINNET_HASH &&
_schainToERC1155[fromChainHash].contains(token)
) {
require(token.isContract(), "Incorrect main chain token");
_removeTransferredAmount(fromChainHash, token, _asSingletonArray(id), _asSingletonArray(amount));
IERC1155Upgradeable(token).safeTransferFrom(address(this), receiver, id, amount, "");
} else {
contractOnSchain.mint(receiver, id, amount, "");
}
emit ERC1155TokenReceived(
fromChainHash,
token,
address(contractOnSchain),
_asSingletonArray(id),
_asSingletonArray(amount)
);
messageProxy.topUpReceiverBalance(payable(receiver));
return receiver;
}
/**
* @dev Allows TokenManager to send a batch of ERC1155 tokens.
*
* Emits a {ERC20TokenCreated} event if token did not exist and was automatically deployed.
* Emits a {ERC20TokenReceived} event on success.
*/
function _sendERC1155Batch(SchainHash fromChainHash, bytes calldata data) private returns (address) {
Messages.MessageType messageType = Messages.getMessageType(data);
address receiver;
address token;
uint256[] memory ids;
uint256[] memory amounts;
ERC1155OnChain contractOnSchain;
if (messageType == Messages.MessageType.TRANSFER_ERC1155_BATCH){
Messages.TransferErc1155BatchMessage memory message = Messages.decodeTransferErc1155BatchMessage(data);
receiver = message.receiver;
token = message.token;
ids = message.ids;
amounts = message.amounts;
contractOnSchain = clonesErc1155[fromChainHash][token];
} else {
Messages.TransferErc1155BatchAndTokenInfoMessage memory message =
Messages.decodeTransferErc1155BatchAndTokenInfoMessage(data);
receiver = message.baseErc1155Batchtransfer.receiver;
token = message.baseErc1155Batchtransfer.token;
ids = message.baseErc1155Batchtransfer.ids;
amounts = message.baseErc1155Batchtransfer.amounts;
contractOnSchain = clonesErc1155[fromChainHash][token];
if (address(contractOnSchain) == address(0)) {
require(automaticDeploy, "Automatic deploy is disabled");
contractOnSchain = new ERC1155OnChain(message.tokenInfo.uri);
clonesErc1155[fromChainHash][token] = contractOnSchain;
emit ERC1155TokenCreated(fromChainHash, token, address(contractOnSchain));
}
}
if (
messageType == Messages.MessageType.TRANSFER_ERC1155_BATCH &&
fromChainHash != MAINNET_HASH &&
_schainToERC1155[fromChainHash].contains(token)
) {
require(token.isContract(), "Incorrect main chain token");
_removeTransferredAmount(fromChainHash, token, ids, amounts);
IERC1155Upgradeable(token).safeBatchTransferFrom(address(this), receiver, ids, amounts, "");
} else {
contractOnSchain.mintBatch(receiver, ids, amounts, "");
}
emit ERC1155TokenReceived(fromChainHash, token, address(contractOnSchain), ids, amounts);
messageProxy.topUpReceiverBalance(payable(receiver));
return receiver;
}
/**
* @dev Burn tokens on schain and send message to unlock them on target chain.
*/
function _exit(
SchainHash chainHash,
address messageReceiver,
address contractOnMainChain,
address to,
uint256 id,
uint256 amount
)
private
{
bool isMainChainToken;
ERC1155OnChain contractOnSchain = clonesErc1155[chainHash][contractOnMainChain];
if (address(contractOnSchain) == address(0)) {
contractOnSchain = ERC1155OnChain(contractOnMainChain);
require(!addedClones[contractOnSchain], "Incorrect main chain token");
isMainChainToken = true;
}
require(address(contractOnSchain).isContract(), "No token clone on schain");
require(contractOnSchain.isApprovedForAll(msg.sender, address(this)), "Not allowed ERC1155 Token");
bytes memory data = Messages.encodeTransferErc1155Message(contractOnMainChain, to, id, amount);
if (isMainChainToken) {
require(chainHash != MAINNET_HASH, "Main chain token could not be transfered to Mainnet");
data = _receiveERC1155(
chainHash,
address(contractOnSchain),
msg.sender,
id,
amount
);
_saveTransferredAmount(
chainHash,
address(contractOnSchain),
_asSingletonArray(id),
_asSingletonArray(amount)
);
contractOnSchain.safeTransferFrom(msg.sender, address(this), id, amount, "");
} else {
contractOnSchain.burn(msg.sender, id, amount);
}
messageProxy.postOutgoingMessage(chainHash, messageReceiver, data);
}
/**
* @dev Burn batch of tokens on schain and send message to unlock them on target chain.
*/
function _exitBatch(
SchainHash chainHash,
address messageReceiver,
address contractOnMainChain,
address to,
uint256[] calldata ids,
uint256[] calldata amounts
)
private
{
bool isMainChainToken;
ERC1155OnChain contractOnSchain = clonesErc1155[chainHash][contractOnMainChain];
if (address(contractOnSchain) == address(0)) {
contractOnSchain = ERC1155OnChain(contractOnMainChain);
require(!addedClones[contractOnSchain], "Incorrect main chain token");
isMainChainToken = true;
}
require(address(contractOnSchain).isContract(), "No token clone on schain");
require(contractOnSchain.isApprovedForAll(msg.sender, address(this)), "Not allowed ERC1155 Token");
bytes memory data = Messages.encodeTransferErc1155BatchMessage(contractOnMainChain, to, ids, amounts);
if (isMainChainToken) {
require(chainHash != MAINNET_HASH, "Main chain token could not be transfered to Mainnet");
data = _receiveERC1155Batch(
chainHash,
address(contractOnSchain),
msg.sender,
ids,
amounts
);
_saveTransferredAmount(chainHash, address(contractOnSchain), ids, amounts);
contractOnSchain.safeBatchTransferFrom(msg.sender, address(this), ids, amounts, "");
} else {
contractOnSchain.burnBatch(msg.sender, ids, amounts);
}
messageProxy.postOutgoingMessage(chainHash, messageReceiver, data);
}
/**
* @dev Saves amount of tokens that was transferred to schain.
*/
function _saveTransferredAmount(
SchainHash chainHash,
address erc1155Token,
uint256[] memory ids,
uint256[] memory amounts
) private {
require(ids.length == amounts.length, "Incorrect length of arrays");
for (uint256 i = 0; i < ids.length; i++)
transferredAmount[chainHash][erc1155Token][ids[i]] += amounts[i];
}
/**
* @dev Removes amount of tokens that was transferred from schain.
*/
function _removeTransferredAmount(
SchainHash chainHash,
address erc1155Token,
uint256[] memory ids,
uint256[] memory amounts
) private {
require(ids.length == amounts.length, "Incorrect length of arrays");
for (uint256 i = 0; i < ids.length; i++)
transferredAmount[chainHash][erc1155Token][ids[i]] -= amounts[i];
}
/**
* @dev Allows DepositBoxERC1155 to receive ERC1155 tokens.
*
* Emits an {ERC1155TokenReady} event.
*
* Requirements:
*
* - Whitelist should be turned off for auto adding tokens to DepositBoxERC1155.
*/
function _receiveERC1155(
SchainHash chainHash,
address erc1155OnMainChain,
address to,
uint256 id,
uint256 amount
)
private
returns (bytes memory data)
{
bool isERC1155AddedToSchain = _schainToERC1155[chainHash].contains(erc1155OnMainChain);
if (!isERC1155AddedToSchain) {
_addERC1155ForSchain(chainHash, erc1155OnMainChain);
data = Messages.encodeTransferErc1155AndTokenInfoMessage(
erc1155OnMainChain,
to,
id,
amount,
_getTokenInfo(IERC1155MetadataURIUpgradeable(erc1155OnMainChain))
);
} else {
data = Messages.encodeTransferErc1155Message(erc1155OnMainChain, to, id, amount);
}
emit ERC1155TokenReady(chainHash, erc1155OnMainChain, _asSingletonArray(id), _asSingletonArray(amount));
}
/**
* @dev Allows DepositBoxERC1155 to receive ERC1155 tokens.
*
* Emits an {ERC1155TokenReady} event.
*
* Requirements:
*
* - Whitelist should be turned off for auto adding tokens to DepositBoxERC1155.
*/
function _receiveERC1155Batch(
SchainHash chainHash,
address erc1155OnMainChain,
address to,
uint256[] calldata ids,
uint256[] calldata amounts
)
private
returns (bytes memory data)
{
bool isERC1155AddedToSchain = _schainToERC1155[chainHash].contains(erc1155OnMainChain);
if (!isERC1155AddedToSchain) {
_addERC1155ForSchain(chainHash, erc1155OnMainChain);
data = Messages.encodeTransferErc1155BatchAndTokenInfoMessage(
erc1155OnMainChain,
to,
ids,
amounts,
_getTokenInfo(IERC1155MetadataURIUpgradeable(erc1155OnMainChain))
);
} else {
data = Messages.encodeTransferErc1155BatchMessage(erc1155OnMainChain, to, ids, amounts);
}
emit ERC1155TokenReady(chainHash, erc1155OnMainChain, ids, amounts);
}
/**
* @dev Adds an ERC1155 token to DepositBoxERC1155.
*
* Emits an {ERC1155TokenAdded} event.
*
* Requirements:
*
* - Given address should be contract.
*/
function _addERC1155ForSchain(SchainHash chainHash, address erc1155OnMainChain) private {
require(erc1155OnMainChain.isContract(), "Given address is not a contract");
require(!_schainToERC1155[chainHash].contains(erc1155OnMainChain), "ERC1155 Token was already added");
_schainToERC1155[chainHash].add(erc1155OnMainChain);
emit ERC1155TokenAdded(chainHash, erc1155OnMainChain, address(0));
}
/**
* @dev Returns info about ERC1155 token.
*/
function _getTokenInfo(
IERC1155MetadataURIUpgradeable erc1155
)
private
view
returns (Messages.Erc1155TokenInfo memory)
{
return Messages.Erc1155TokenInfo({uri: erc1155.uri(0)});
}
/**
* @dev Create array with single element in it.
*/
function _asSingletonArray(uint256 element) private pure returns (uint256[] memory array) {
array = new uint256[](1);
array[0] = element;
}
}
exec
/bin/bash -lc "sed -n '1,220p' contracts/extensions/ERC721ReferenceMintAndMetadataMainnet.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ERC721ReferenceMintAndMetadataMainnet.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataMainnet.sol";
import "../schain/tokens/ERC721OnChain.sol";
import "./interfaces/MessageReceiver.sol";
// This contract runs on the main net and accepts deposits
contract ERC721ReferenceMintAndMetadataMainnet is MessageReceiver, IERC721ReferenceMintAndMetadataMainnet {
address public immutable erc721ContractOnMainnet;
address public senderContractOnSchain;
string public schainName;
address public immutable owner;
modifier onlyOwner() {
require(msg.sender == owner, "Sender is not an owner");
_;
}
constructor(
address newMessageProxyAddress,
address newErc721Contract,
string memory newSchainName
)
MessageProxyClient(newMessageProxyAddress)
{
require(newErc721Contract != address(0), "ERC721 contract has to be set");
erc721ContractOnMainnet = newErc721Contract;
schainName = newSchainName;
owner = msg.sender;
}
function setSenderContractOnSchain(address newSenderContractOnSchain) external override onlyOwner {
require(newSenderContractOnSchain != address(0), "Sender contract has to be set");
senderContractOnSchain = newSenderContractOnSchain;
}
function postMessage(
SchainHash schainHash,
address sender,
bytes calldata data
)
external
override
onlyMessageProxy
{
require(schainHash == SchainHash.wrap(keccak256(abi.encodePacked(schainName))), "Incorrect name of schain");
require(sender == senderContractOnSchain, "Incorrect sender contract");
address to;
uint256 tokenId;
string memory tokenURI;
(to, tokenId, tokenURI) = abi.decode(data, (address, uint256, string));
ERC721OnChain(erc721ContractOnMainnet).mint(address(this), tokenId);
require(
ERC721OnChain(erc721ContractOnMainnet).setTokenURI(tokenId, tokenURI),
"Token URI was not set"
);
ERC721OnChain(erc721ContractOnMainnet).transferFrom(address(this), to, tokenId);
}
}
exec
/bin/bash -lc "sed -n '1,180p' contracts/extensions/ERC721ReferenceMintAndMetadataSchain.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ERC721ReferenceMintAndMetadataSchain.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2019-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@skalenetwork/ima-interfaces/extensions/IERC721ReferenceMintAndMetadataSchain.sol";
import "../schain/tokens/ERC721OnChain.sol";
import "./interfaces/MessageSender.sol";
/**
* @title Token Manager
* @dev Runs on SKALE Chains, accepts messages from mainnet, and instructs
* TokenFactory to create clones.
When a user exits a SKALE chain, TokenFactory
* burns tokens.
*/
contract ERC721ReferenceMintAndMetadataSchain is MessageSender, IERC721ReferenceMintAndMetadataSchain {
address public immutable erc721ContractOnSchain;
address public immutable receiverContractOnMainnet;
constructor(
address newMessageProxyAddress,
address newErc721ContractOnSchain,
address newReceiverContractOnMainnet
)
MessageProxyClient(newMessageProxyAddress)
{
require(newErc721ContractOnSchain != address(0), "ERC721 contract has to be set");
require(newReceiverContractOnMainnet != address(0), "Receiver contract has to be set");
erc721ContractOnSchain = newErc721ContractOnSchain;
receiverContractOnMainnet = newReceiverContractOnMainnet;
}
function sendTokenToMainnet(address receiver, uint256 tokenId) external override {
require(
ERC721OnChain(erc721ContractOnSchain).getApproved(tokenId) == address(this),
"Not allowed ERC721 Token"
);
ERC721OnChain(erc721ContractOnSchain).transferFrom(msg.sender, address(this), tokenId);
string memory tokenURI = ERC721OnChain(erc721ContractOnSchain).tokenURI(tokenId);
ERC721OnChain(erc721ContractOnSchain).burn(tokenId);
bytes memory data = encodeParams(receiver, tokenId, tokenURI);
_sendMessage("Mainnet", receiverContractOnMainnet, data);
}
function encodeParams(
address receiver,
uint256 tokenId,
string memory tokenURI
)
public
pure
override
returns (bytes memory data)
{
data = abi.encode(receiver, tokenId, tokenURI);
}
}
exec
/bin/bash -lc "sed -n '1,140p' contracts/extensions/interfaces/MessageProxyClient.sol && printf '\\n=====\\n' && sed -n '1,120p' contracts/extensions/interfaces/MessageReceiver.sol && printf '\\n=====\\n' && sed -n '1,120p' contracts/extensions/interfaces/MessageSender.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* MessageProxyClient.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "../../MessageProxy.sol";
abstract contract MessageProxyClient {
MessageProxy public immutable messageProxy;
modifier onlyMessageProxy() {
require(msg.sender == address(messageProxy), "Sender is not a message proxy");
_;
}
constructor(address newMessageProxyAddress) {
messageProxy = MessageProxy(newMessageProxyAddress);
}
}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/**
* MessageReceiver.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@skalenetwork/ima-interfaces/IMessageReceiver.sol";
import "./MessageProxyClient.sol";
// solhint-disable-next-line no-empty-blocks
abstract contract MessageReceiver is MessageProxyClient, IMessageReceiver {}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/**
* MessageSender.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "./MessageProxyClient.sol";
abstract contract MessageSender is MessageProxyClient {
function _sendMessage(
string memory targetChainName,
address targetContract,
bytes memory data
) internal {
messageProxy.postOutgoingMessage(
SchainHash.wrap(keccak256(abi.encodePacked(targetChainName))),
targetContract,
data
);
}
}
exec
/bin/bash -lc "sed -n '1,180p' contracts/schain/tokens/ERC20OnChain.sol && printf '\\n=====\\n' && sed -n '1,220p' contracts/schain/tokens/ERC721OnChain.sol && printf '\\n=====\\n' && sed -n '1,180p' contracts/schain/tokens/ERC1155OnChain.sol && printf '\\n=====\\n' && sed -n '1,180p' contracts/schain/tokens/EthErc20.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ERC20OnChain.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/tokens/IERC20OnChain.sol";
/**
* @title ERC20OnChain
* @dev ERC20 token that is used as an automatically deployed clone of ERC20 on mainnet.
*/
contract ERC20OnChain is AccessControlEnumerableUpgradeable, ERC20BurnableUpgradeable, IERC20OnChain {
/**
* @dev id of a role that allows token minting.
*/
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
constructor(
string memory contractName,
string memory contractSymbol
) initializer
{
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init();
ERC20Upgradeable.__ERC20_init(contractName, contractSymbol);
ERC20BurnableUpgradeable.__ERC20Burnable_init();
_setRoleAdmin(MINTER_ROLE, MINTER_ROLE);
_setupRole(MINTER_ROLE, _msgSender());
}
/**
* @dev Mint tokens.
*
* Requirements:
*
* - sender must be granted with {MINTER_ROLE}.
*/
function mint(address account, uint256 value) external override {
require(hasRole(MINTER_ROLE, _msgSender()), "Sender is not a Minter");
_mint(account, value);
}
}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ERC721OnChain.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/tokens/IERC721OnChain.sol";
/**
* @title ERC721OnChain
* @dev ERC721 token that is used as an automatically deployed clone of ERC721 on mainnet.
*/
contract ERC721OnChain is
AccessControlEnumerableUpgradeable,
ERC721BurnableUpgradeable,
ERC721URIStorageUpgradeable,
IERC721OnChain
{
/**
* @dev id of a role that allows token minting.
*/
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
constructor(
string memory contractName,
string memory contractSymbol
) initializer
{
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init();
ERC721Upgradeable.__ERC721_init(contractName, contractSymbol);
ERC721BurnableUpgradeable.__ERC721Burnable_init();
_setRoleAdmin(MINTER_ROLE, MINTER_ROLE);
_setupRole(MINTER_ROLE, _msgSender());
}
/**
* @dev Set URI of ERC721 token.
*
* Requirements:
*
* - token with {tokenId} must exist.
* - sender must be the token owner or approved for the token.
*/
function setTokenURI(uint256 tokenId, string calldata tokenUri)
external
override
returns (bool)
{
require(_exists(tokenId), "Token does not exists");
require(
_isApprovedOrOwner(msg.sender, tokenId) ||
hasRole(MINTER_ROLE, _msgSender()),
"Sender can not set token URI"
);
_setTokenURI(tokenId, tokenUri);
return true;
}
/**
* @dev Mint token.
*
* Requirements:
*
* - sender must be granted with {MINTER_ROLE}.
*/
function mint(address account, uint256 tokenId)
external
override
{
require(hasRole(MINTER_ROLE, _msgSender()), "Sender is not a Minter");
_mint(account, tokenId);
}
/**
* @dev Check if contract support {interfaceId} interface.
*
* See https://eips.ethereum.org/EIPS/eip-165 for more details.
*/
function supportsInterface(
bytes4 interfaceId
)
public
view
override(AccessControlEnumerableUpgradeable, ERC721Upgradeable, ERC721URIStorageUpgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
/**
* @dev Get token URI.
*/
function tokenURI(
uint256 tokenId
)
public
view
override (ERC721Upgradeable, ERC721URIStorageUpgradeable)
returns (string memory)
{
return ERC721URIStorageUpgradeable.tokenURI(tokenId);
}
// private
/**
* @dev Burn {tokenId}.
*/
function _burn(uint256 tokenId) internal override (ERC721Upgradeable, ERC721URIStorageUpgradeable) {
ERC721URIStorageUpgradeable._burn(tokenId);
}
}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ERC1155OnChain.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/tokens/IERC1155OnChain.sol";
/**
* @title ERC1155OnChain
* @dev ERC1155 token that is used as an automatically deployed clone of ERC1155 on mainnet.
*/
contract ERC1155OnChain is AccessControlEnumerableUpgradeable, ERC1155BurnableUpgradeable, IERC1155OnChain {
/**
* @dev id of a role that allows token minting.
*/
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
constructor(
string memory uri
) initializer
{
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init();
ERC1155Upgradeable.__ERC1155_init(uri);
ERC1155BurnableUpgradeable.__ERC1155Burnable_init();
_setRoleAdmin(MINTER_ROLE, MINTER_ROLE);
_setupRole(MINTER_ROLE, _msgSender());
}
/**
* @dev Mint tokens.
*
* Requirements:
*
* - sender must be granted with {MINTER_ROLE}.
*/
function mint(
address account,
uint256 id,
uint256 amount,
bytes memory data
)
external
override
{
require(hasRole(MINTER_ROLE, _msgSender()), "Sender is not a Minter");
_mint(account, id, amount, data);
}
/**
* @dev Mint batch of tokens.
*
* Requirements:
*
* - sender must be granted with {MINTER_ROLE}.
*/
function mintBatch(
address account,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
external
override
{
require(hasRole(MINTER_ROLE, _msgSender()), "Sender is not a Minter");
_mintBatch(account, ids, amounts, data);
}
/**
* @dev Check if contract support {interfaceId} interface.
*
* See https://eips.ethereum.org/EIPS/eip-165 for more details.
*/
function supportsInterface(
bytes4 interfaceId
)
public
view
override(AccessControlEnumerableUpgradeable, ERC1155Upgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/**
* EthErc20.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2019-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@skalenetwork/ima-interfaces/schain/tokens/IEthErc20.sol";
/**
* @title EthErc20
* @dev ERC20 token that represents ETH on mainnet.
*/
contract EthErc20 is AccessControlEnumerableUpgradeable, ERC20BurnableUpgradeable, IEthErc20 {
/**
* @dev id of a role that allows token minting.
*/
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
/**
* @dev id of a role that allows token burning.
*/
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
/**
* @dev Mint tokens.
*
* Requirements:
*
* - sender must be granted with {MINTER_ROLE}.
*/
function mint(address account, uint256 amount) external override {
require(hasRole(MINTER_ROLE, _msgSender()), "MINTER role is required");
_mint(account, amount);
}
/**
* @dev Burn tokens for any account.
*
* Requirements:
*
* - sender must be granted with {BURNER_ROLE}.
*/
function forceBurn(address account, uint256 amount) external override {
require(hasRole(BURNER_ROLE, _msgSender()), "BURNER role is required");
_burn(account, amount);
}
/**
* @dev Is called once during contract deployment.
*/
function initialize(address tokenManagerEthAddress)
external
override
initializer
{
AccessControlEnumerableUpgradeable.__AccessControlEnumerable_init();
ERC20Upgradeable.__ERC20_init("ERC20 Ether Clone", "ETHC");
ERC20BurnableUpgradeable.__ERC20Burnable_init();
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(MINTER_ROLE, tokenManagerEthAddress);
_setupRole(BURNER_ROLE, tokenManagerEthAddress);
}
}
exec
/bin/bash -lc "sed -n '1,220p' contracts/test/SkaleVerifierMock.sol && printf '\\n=====\\n' && sed -n '1,140p' contracts/test/MessageProxyForSchainWithoutSignature.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/**
* TestSkaleVerifier.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Artem Payvin
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "../schain/bls/FieldOperations.sol";
import "./PrecompiledMock.sol";
interface ISkaleVerifierMock {
function verify(
IFieldOperations.Fp2Point calldata signature,
bytes32 hash,
uint counter,
uint hashA,
uint hashB,
IFieldOperations.G2Point calldata publicKey
)
external
view
returns (bool);
}
contract SkaleVerifierMock is ISkaleVerifierMock {
/**
* @dev Verifies a BLS signature.
*
* Requirements:
*
* - Signature is in G1.
* - Hash is in G1.
* - G2.one in G2.
* - Public Key in G2.
*/
function verify(
IFieldOperations.Fp2Point calldata signature,
bytes32 hash,
uint counter,
uint hashA,
uint hashB,
IFieldOperations.G2Point calldata publicKey
)
external
view
override
returns (bool)
{
require(G1Operations.checkRange(signature), "Signature is not valid");
if (!_checkHashToGroupWithHelper(
hash,
counter,
hashA,
hashB
)
)
{
return false;
}
uint newSignB = G1Operations.negate(signature.b);
require(G1Operations.isG1Point(signature.a, newSignB) || true, "Sign not in G1");
require(G1Operations.isG1Point(hashA, hashB) || true, "Hash not in G1");
IFieldOperations.G2Point memory g2 = G2Operations.getG2Generator();
require(
G2Operations.isG2(publicKey),
"Public Key not in G2"
);
return PrecompiledMock.bn256Pairing(
signature.a, newSignB,
g2.x.b, g2.x.a, g2.y.b, g2.y.a,
hashA, hashB,
publicKey.x.b, publicKey.x.a, publicKey.y.b, publicKey.y.a
);
// return true;
}
function _checkHashToGroupWithHelper(
bytes32 hash,
uint counter,
uint hashA,
uint hashB
)
private
pure
returns (bool)
{
if (counter > 100) {
return false;
}
uint xCoordinate = uint(hash) % Fp2Operations.P;
xCoordinate = (xCoordinate + counter) % Fp2Operations.P;
uint ySquared = addmod(
mulmod(mulmod(xCoordinate, xCoordinate, Fp2Operations.P), xCoordinate, Fp2Operations.P),
3,
Fp2Operations.P
);
if (hashB < Fp2Operations.P / 2 || mulmod(hashB, hashB, Fp2Operations.P) != ySquared || xCoordinate != hashA) {
return true;
}
return true;
}
}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/**
* MessageProxyForSchainWithoutSignature.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "./MessageProxyForSchainTester.sol";
contract MessageProxyForSchainWithoutSignature is MessageProxyForSchainTester {
constructor(string memory schainName)
MessageProxyForSchainTester(IKeyStorage(address(0)), schainName)
// solhint-disable-next-line no-empty-blocks
{}
function _verifyMessages(
bytes32,
Signature calldata
)
internal
pure
override
returns (bool)
{
return true;
}
}
exec
/bin/bash -lc "sed -n '1,220p' contracts/schain/bls/SkaleVerifier.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/*
SkaleVerifier.sol - SKALE Manager
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaiev
SKALE Manager is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "./Precompiled.sol";
import "./FieldOperations.sol";
/**
* @title SkaleVerifier
* @dev Contains verify function to perform BLS signature verification.
*/
library SkaleVerifier {
using Fp2Operations for IFieldOperations.Fp2Point;
/**
* @dev Verifies a BLS signature.
*
* Requirements:
*
* - Signature is in G1.
* - Hash is in G1.
* - G2.one in G2.
* - Public Key in G2.
*/
function verify(
IFieldOperations.Fp2Point memory signature,
bytes32 hash,
uint counter,
uint hashA,
uint hashB,
IFieldOperations.G2Point memory publicKey
)
internal
view
returns (bool)
{
require(G1Operations.checkRange(signature), "Signature is not valid");
if (!_checkHashToGroupWithHelper(
hash,
counter,
hashA,
hashB
)
)
{
return false;
}
uint newSignB = G1Operations.negate(signature.b);
require(G1Operations.isG1Point(signature.a, newSignB), "Sign not in G1");
require(G1Operations.isG1Point(hashA, hashB), "Hash not in G1");
IFieldOperations.G2Point memory g2 = G2Operations.getG2Generator();
require(
G2Operations.isG2(publicKey),
"Public Key not in G2"
);
return Precompiled.bn256Pairing(
signature.a, newSignB,
g2.x.b, g2.x.a, g2.y.b, g2.y.a,
hashA, hashB,
publicKey.x.b, publicKey.x.a, publicKey.y.b, publicKey.y.a
);
}
function _checkHashToGroupWithHelper(
bytes32 hash,
uint counter,
uint hashA,
uint hashB
)
private
pure
returns (bool)
{
if (counter > 100) {
return false;
}
uint xCoordinate = uint(hash) % Fp2Operations.P;
xCoordinate = (xCoordinate + counter) % Fp2Operations.P;
uint ySquared = addmod(
mulmod(mulmod(xCoordinate, xCoordinate, Fp2Operations.P), xCoordinate, Fp2Operations.P),
3,
Fp2Operations.P
);
if (hashB < Fp2Operations.P / 2 || mulmod(hashB, hashB, Fp2Operations.P) != ySquared || xCoordinate != hashA) {
return false;
}
return true;
}
}
exec
/bin/bash -lc "sed -n '1,180p' contracts/schain/bls/Precompiled.sol && printf '\\n=====\\n' && sed -n '1,380p' contracts/schain/bls/FieldOperations.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: AGPL-3.0-only
/*
Precompiled.sol - SKALE Manager
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaiev
SKALE Manager is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
/**
* @title Precompiled
* @dev This library is a wrapper to call precompiled contracts
*
* Defined calls:
*
* - bn256Pairing
*/
library Precompiled {
/**
* @dev Calls precompiled contract with address 0x8
* for elliptic curve pairing operations are required in order to perform zkSNARK verification
* within the block gas limit.
* see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md for more details
*/
function bn256Pairing(
uint x1,
uint y1,
uint a1,
uint b1,
uint c1,
uint d1,
uint x2,
uint y2,
uint a2,
uint b2,
uint c2,
uint d2)
internal view returns (bool)
{
bool success;
uint[12] memory inputToPairing;
inputToPairing[0] = x1;
inputToPairing[1] = y1;
inputToPairing[2] = a1;
inputToPairing[3] = b1;
inputToPairing[4] = c1;
inputToPairing[5] = d1;
inputToPairing[6] = x2;
inputToPairing[7] = y2;
inputToPairing[8] = a2;
inputToPairing[9] = b2;
inputToPairing[10] = c2;
inputToPairing[11] = d2;
uint[1] memory out;
// solhint-disable-next-line no-inline-assembly
assembly {
success := staticcall(not(0), 8, inputToPairing, mul(12, 0x20), out, 0x20)
}
require(success, "Pairing check failed");
return out[0] != 0;
}
}
=====
// SPDX-License-Identifier: AGPL-3.0-only
/*
FieldOperations.sol - SKALE Manager
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaiev
SKALE Manager is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity 0.8.27;
import "@skalenetwork/ima-interfaces/schain/bls/IFieldOperations.sol";
import "./Precompiled.sol";
/**
* @title Fp2Operations
* @dev This library contains operations of field that is an extension by imaginary unit of
* a field of division remainders of a prime number
*
* Element of field is Fp2Point
*
* Prime divisor is P
*
* Defined operations:
*
* - addition
* - subtraction
* - scalar multiplication
* - multiplication
* - squaring
* - comparison for equality
*/
library Fp2Operations {
/**
* @dev Prime devisor
*/
uint constant public P = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
/**
* @dev Add {value1} to {value2}
*/
function addFp2(
IFieldOperations.Fp2Point memory value1,
IFieldOperations.Fp2Point memory value2
)
internal
pure
returns (IFieldOperations.Fp2Point memory)
{
return IFieldOperations.Fp2Point({ a: addmod(value1.a, value2.a, P), b: addmod(value1.b, value2.b, P) });
}
/**
* @dev Perform scalar multiplication of {value} by {scalar}
*/
function scalarMulFp2(
IFieldOperations.Fp2Point memory value,
uint scalar
)
internal
pure
returns (IFieldOperations.Fp2Point memory)
{
return IFieldOperations.Fp2Point({ a: mulmod(scalar, value.a, P), b: mulmod(scalar, value.b, P) });
}
/**
* @dev Subtract {subtracted} from {diminished}
*/
function minusFp2(
IFieldOperations.Fp2Point memory diminished,
IFieldOperations.Fp2Point memory subtracted
)
internal
pure
returns (IFieldOperations.Fp2Point memory difference)
{
uint p = P;
if (diminished.a >= subtracted.a) {
difference.a = addmod(diminished.a, p - subtracted.a, p);
} else {
difference.a = (p - addmod(subtracted.a, p - diminished.a, p)) % p;
}
if (diminished.b >= subtracted.b) {
difference.b = addmod(diminished.b, p - subtracted.b, p);
} else {
difference.b = (p - addmod(subtracted.b, p - diminished.b, p)) % p;
}
}
/**
* @dev Multiply {value1} by {value2}
*/
function mulFp2(
IFieldOperations.Fp2Point memory value1,
IFieldOperations.Fp2Point memory value2
)
internal
pure
returns (IFieldOperations.Fp2Point memory result)
{
uint p = P;
IFieldOperations.Fp2Point memory point = IFieldOperations.Fp2Point({
a: mulmod(value1.a, value2.a, p),
b: mulmod(value1.b, value2.b, p)});
result.a = addmod(
point.a,
mulmod(p - 1, point.b, p),
p);
result.b = addmod(
mulmod(
addmod(value1.a, value1.b, p),
addmod(value2.a, value2.b, p),
p),
p - addmod(point.a, point.b, p),
p);
}
/**
* @dev Square {value}
*/
function squaredFp2(
IFieldOperations.Fp2Point memory value
)
internal
pure
returns (IFieldOperations.Fp2Point memory)
{
uint p = P;
uint ab = mulmod(value.a, value.b, p);
uint multiplication = mulmod(addmod(value.a, value.b, p), addmod(value.a, mulmod(p - 1, value.b, p), p), p);
return IFieldOperations.Fp2Point({ a: multiplication, b: addmod(ab, ab, p) });
}
/**
* @dev Check if {value1} is equal to {value2}
*/
function isEqual(
IFieldOperations.Fp2Point memory value1,
IFieldOperations.Fp2Point memory value2
)
internal
pure
returns (bool)
{
return value1.a == value2.a && value1.b == value2.b;
}
}
/**
* @title G1Operations
* @dev This library contains operations of a group of elements {x, y}
* where y^2 = x^3 + 3 mod P and (x + iy) is an element of Fp2
*
* Element of the group is Fp2Point
*
* Prime divisor is Fp2Operations.P
*
* A group generator is {1, 2}
*
* Defined operations:
*
* - check if a point is in the group G1
* - check if a point is in the field Fp2
* - for x of Fp calculate -x
*/
library G1Operations {
using Fp2Operations for IFieldOperations.Fp2Point;
/**
* @dev Get G1 group generator
*/
function getG1Generator() internal pure returns (IFieldOperations.Fp2Point memory) {
// Current solidity version does not support Constants of non-value type
// so we implemented this function
return IFieldOperations.Fp2Point({
a: 1,
b: 2
});
}
/**
* @dev Check if ({x], {y}) is a G1 element
*/
function isG1Point(uint x, uint y) internal pure returns (bool) {
uint p = Fp2Operations.P;
return mulmod(y, y, p) ==
addmod(mulmod(mulmod(x, x, p), x, p), 3, p);
}
/**
* @dev Check if {point} is a G1 element
*/
function isG1(IFieldOperations.Fp2Point memory point) internal pure returns (bool) {
return isG1Point(point.a, point.b);
}
/**
* @dev Check if {point} is a Fp2 element
*/
function checkRange(IFieldOperations.Fp2Point memory point) internal pure returns (bool) {
return point.a < Fp2Operations.P && point.b < Fp2Operations.P;
}
/**
* @dev For {y} of Fp calculate -y
*/
function negate(uint y) internal pure returns (uint) {
return (Fp2Operations.P - y) % Fp2Operations.P;
}
}
/**
* @title G2Operations
* @dev This library contains operations of a group of elements {x, y}
* where y^2 = x^3 + TWISTB and x and y are elements of Fp2
*
* Element of the group is G2Point
*
* Prime divisor is Fp2Operations.P
* TWISTB is
* {
* 19485874751759354771024239261021720505790618469301721065564631296452457478373,
* 266929791119991161246907387137283842545076965332900288569378510910307636690
* }
* A group generator is
* {
* {
* 10857046999023057135944570762232829481370756359578518086990519993285655852781,
* 11559732032986387107991004021392285783925812861821192530917403151452391805634
* },
* {
* 8495653923123431417604973247489272438418190587263600148770280649306958101930,
* 4082367875863433681332203403145435568316851327593401208105741076214120093531
* }
* }
*
* Defined operations:
*
* - check if a point is in the group G2
* - check if a point is zero element of group G2
* - comparison for equality
*/
library G2Operations {
using Fp2Operations for IFieldOperations.Fp2Point;
/**
* @dev Get value of TWISTB
*/
function getTWISTB() internal pure returns (IFieldOperations.Fp2Point memory) {
// Current solidity version does not support Constants of non-value type
// so we implemented this function
return IFieldOperations.Fp2Point({
a: 19485874751759354771024239261021720505790618469301721065564631296452457478373,
b: 266929791119991161246907387137283842545076965332900288569378510910307636690
});
}
/**
* @dev Get G2 group generator
*/
function getG2Generator() internal pure returns (IFieldOperations.G2Point memory) {
// Current solidity version does not support Constants of non-value type
// so we implemented this function
return IFieldOperations.G2Point({
x: IFieldOperations.Fp2Point({
a: 10857046999023057135944570762232829481370756359578518086990519993285655852781,
b: 11559732032986387107991004021392285783925812861821192530917403151452391805634
}),
y: IFieldOperations.Fp2Point({
a: 8495653923123431417604973247489272438418190587263600148770280649306958101930,
b: 4082367875863433681332203403145435568316851327593401208105741076214120093531
})
});
}
/**
* @dev Get G2 zero element
*/
function getG2Zero() internal pure returns (IFieldOperations.G2Point memory) {
// Current solidity version does not support Constants of non-value type
// so we implemented this function
return IFieldOperations.G2Point({
x: IFieldOperations.Fp2Point({
a: 0,
b: 0
}),
y: IFieldOperations.Fp2Point({
a: 1,
b: 0
})
});
}
/**
* @dev Check if ({x}, {y}) is an element of G2
*/
function isG2Point(
IFieldOperations.Fp2Point memory x,
IFieldOperations.Fp2Point memory y
)
internal
pure
returns (bool)
{
if (isG2ZeroPoint(x, y)) {
return true;
}
IFieldOperations.Fp2Point memory squaredY = y.squaredFp2();
IFieldOperations.Fp2Point memory res = squaredY.minusFp2(
x.squaredFp2().mulFp2(x)
).minusFp2(getTWISTB());
return res.a == 0 && res.b == 0;
}
/**
* @dev Check if {value} is an element of G2
*/
function isG2(IFieldOperations.G2Point memory value) internal pure returns (bool) {
return isG2Point(value.x, value.y);
}
/**
* @dev Check if ({x}, {y}) is a zero element of G2
*/
function isG2ZeroPoint(
IFieldOperations.Fp2Point memory x,
IFieldOperations.Fp2Point memory y
)
internal
pure
returns (bool)
{
return x.a == 0 && x.b == 0 && y.a == 1 && y.b == 0;
}
/**
* @dev Check if {value} is a zero element of G2
*/
function isG2Zero(IFieldOperations.G2Point memory value) internal pure returns (bool) {
return value.x.a == 0 && value.x.b == 0 && value.y.a == 1 && value.y.b == 0;
}
/**
* @dev Check if {value1} is equal to {value2}
*/
function isEqual(
IFieldOperations.G2Point memory value1,
IFieldOperations.G2Point memory value2
)
internal
pure
returns (bool)
{
return value1.x.isEqual(value2.x) && value1.y.isEqual(value2.y);
}
}
exec
/bin/bash -lc "rg -n \"ERC20TransferWithFalseReturn|ERC20TransferWithoutReturn|ERC20IncorrectTransfer|RevertableERC20|fee|burn.*transfer|tax\" contracts/test contracts -g '"'!contracts/test/erc20/ERC20*'"'" in /tmp/codex-sryvig8b
succeeded in 0ms:
contracts/mainnet/CommunityPool.sol:65: * @dev Emitted when basefee multiplier was changed
contracts/mainnet/CommunityPool.sol:256: * @dev Checks whether passed amount is enough to recharge user wallet with current basefee.
contracts/test/erc20/RevertableERC20.sol:4: * RevertableERC20.sol - SKALE Interchain Messaging Agent
contracts/test/erc20/RevertableERC20.sol:26:interface IRevertableERC20 {
contracts/test/erc20/RevertableERC20.sol:32:contract RevertableERC20 is IRevertableERC20, ERC20Upgradeable {
contracts/test/SafeMock.sol:160: /// (e.g. base transaction fee, signature check, payment of the refund)
contracts/test/erc20/RevertableERC20.sol:4: * RevertableERC20.sol - SKALE Interchain Messaging Agent
contracts/test/erc20/RevertableERC20.sol:26:interface IRevertableERC20 {
contracts/test/erc20/RevertableERC20.sol:32:contract RevertableERC20 is IRevertableERC20, ERC20Upgradeable {
contracts/test/SafeMock.sol:160: /// (e.g. base transaction fee, signature check, payment of the refund)
contracts/schain/CommunityLocker.sol:39: * of gas fees for sent messages
exec
/bin/bash -lc "rg -n \"TransferSkipped|retrieveFor\\(|escalate\\(|validateTransfer\\(|rejectTransfer\\(\" contracts/test" in /tmp/codex-sryvig8b
exited 1 in 0ms:
exec
/bin/bash -lc "nl -ba contracts/mainnet/DepositBoxes/DepositBoxERC20.sol | sed -n '680,715p'
nl -ba contracts/schain/MessageProxyForSchain.sol | sed -n '246,266p'
nl -ba contracts/schain/CommunityLocker.sol | sed -n '252,274p'" in /tmp/codex-sryvig8b
succeeded in 0ms:
680 function depositERC20Direct(
681 string calldata schainName,
682 address erc20OnMainnet,
683 uint256 amount,
684 address receiver
685 )
686 public
687 override
688 rightTransaction(schainName, receiver)
689 whenNotKilled(_schainHash(schainName))
690 {
691 SchainHash schainHash = _schainHash(schainName);
692 address contractReceiver = schainLinks[schainHash];
693 require(contractReceiver != address(0), "Unconnected chain");
694 require(
695 IERC20Upgradeable(erc20OnMainnet).allowance(msg.sender, address(this)) >= amount,
696 "DepositBox was not approved for ERC20 token"
697 );
698 bytes memory data = _receiveERC20(
699 schainName,
700 erc20OnMainnet,
701 receiver,
702 amount
703 );
704 _saveTransferredAmount(schainHash, erc20OnMainnet, amount);
705 IERC20MetadataUpgradeable(erc20OnMainnet).safeTransferFrom(msg.sender, address(this), amount);
706 messageProxy.postOutgoingMessage(
707 schainHash,
708 contractReceiver,
709 data
710 );
711 }
712
713 /**
714 * @dev Check if the receiver is in the delay whitelist
715 */
246 function setMinimumReceiverBalance(uint256 balance) external override onlyConstantSetter {
247 emit MinimumReceiverBalanceChanged(minimumReceiverBalance, balance);
248 minimumReceiverBalance = balance;
249 }
250
251 /**
252 * @dev Sends sFuel to the `receiver` address to satisfy a minimum balance
253 */
254 function topUpReceiverBalance(address payable receiver) external override {
255 require(isContractRegistered(SchainHash.wrap(bytes32(0)), msg.sender), "Sender is not registered");
256 uint256 balance = receiver.balance;
257 uint256 threshold = minimumReceiverBalance;
258 if (balance < threshold) {
259 _transferFromEtherbase(receiver, threshold - balance);
260 }
261 }
262
263 /**
264 * @dev Verify if the message metadata is valid.
265 */
266 function verifyOutgoingMessageData(
252 function setGasPrice(
253 uint gasPrice,
254 uint timestamp,
255 IMessageProxyForSchain.Signature memory
256 )
257 external
258 override
259 {
260 require(timestamp > gasPriceTimestamp, "Gas price timestamp already updated");
261 require(timestamp <= block.timestamp, "Timestamp should not be in the future");
262 // TODO: uncomment when oracle finished
263 // require(
264 // messageProxy.verifySignature(keccak256(abi.encodePacked(gasPrice, timestamp)), signature),
265 // "Signature is not verified"
266 // );
267 emit ConstantUpdated(
268 keccak256(abi.encodePacked("MainnetGasPrice")),
269 mainnetGasPrice,
270 gasPrice
271 );
272 mainnetGasPrice = gasPrice;
273 gasPriceTimestamp = timestamp;
274 }
exec
/bin/bash -lc "nl -ba contracts/mainnet/DepositBoxes/DepositBoxERC20.sol | sed -n '606,780p'" in /tmp/codex-sryvig8b
succeeded in 0ms:
606 /**
607 * @dev Retrieve tokens that were unlocked after delay for specified receiver
608 */
609 function retrieveFor(address receiver) public override {
610 uint256 transfersAmount = MathUpgradeable.min(
611 delayedTransfersByReceiver[receiver].length(),
612 _QUEUE_PROCESSING_LIMIT
613 );
614 uint256 currentIndex = 0;
615 bool retrieved = false;
616 uint256 countToTransfer = 0;
617 DelayedTransfer[] memory transfers = new DelayedTransfer[](transfersAmount);
618 uint256[] memory transfersIds = new uint256[](transfersAmount);
619 for (uint256 i = 0; i < transfersAmount; ++i) {
620 uint256 transferId = uint256(delayedTransfersByReceiver[receiver].at(currentIndex++));
621 DelayedTransfer memory transfer = delayedTransfers[transferId];
622 if (transfer.status != DelayedTransferStatus.COMPLETED) {
623 if (block.timestamp < transfer.untilTimestamp) {
624 // disable detector until slither fixes false positive
625 // https://github.com/crytic/slither/issues/778
626 // slither-disable-next-line incorrect-equality
627 if (transfer.status == DelayedTransferStatus.DELAYED) {
628 break;
629 } // else status is ARBITRAGE -> continue
630 } else { // it's time to unlock
631 if (currentIndex == 1) {
632 --currentIndex;
633 _removeOldestDelayedTransfer(receiver);
634 } else {
635 delayedTransfers[transferId].status = DelayedTransferStatus.COMPLETED;
636 }
637 retrieved = true;
638 transfers[countToTransfer] = transfer;
639 transfersIds[countToTransfer] = transferId;
640 ++countToTransfer;
641 }
642 } else { // status is COMPLETED
643 if (currentIndex == 1) {
644 --currentIndex;
645 retrieved = true;
646 _removeOldestDelayedTransfer(receiver);
647 }
648 }
649 }
650 require(retrieved, "There are no transfers available for retrieving");
651 _doNTransfers(transfers, transfersIds, countToTransfer);
652 }
653
654 /**
655 * @dev Creates a new DepositBoxERC20 contract.
656 */
657 function initialize(
658 IContractManager contractManagerOfSkaleManagerValue,
659 ILinker linkerValue,
660 IMessageProxyForMainnet messageProxyValue
661 )
662 public
663 override(DepositBox, IDepositBox)
664 initializer
665 {
666 DepositBox.initialize(contractManagerOfSkaleManagerValue, linkerValue, messageProxyValue);
667 }
668
669 /**
670 * @dev Allows `msg.sender` to send ERC20 token from mainnet to schain to specified receiver.
671 *
672 * Requirements:
673 *
674 * - Schain name must not be `Mainnet`.
675 * - Receiver account on schain cannot be null.
676 * - Schain that receives tokens should not be killed.
677 * - Receiver contract should be defined.
678 * - `msg.sender` should approve their tokens for DepositBoxERC20 address.
679 */
680 function depositERC20Direct(
681 string calldata schainName,
682 address erc20OnMainnet,
683 uint256 amount,
684 address receiver
685 )
686 public
687 override
688 rightTransaction(schainName, receiver)
689 whenNotKilled(_schainHash(schainName))
690 {
691 SchainHash schainHash = _schainHash(schainName);
692 address contractReceiver = schainLinks[schainHash];
693 require(contractReceiver != address(0), "Unconnected chain");
694 require(
695 IERC20Upgradeable(erc20OnMainnet).allowance(msg.sender, address(this)) >= amount,
696 "DepositBox was not approved for ERC20 token"
697 );
698 bytes memory data = _receiveERC20(
699 schainName,
700 erc20OnMainnet,
701 receiver,
702 amount
703 );
704 _saveTransferredAmount(schainHash, erc20OnMainnet, amount);
705 IERC20MetadataUpgradeable(erc20OnMainnet).safeTransferFrom(msg.sender, address(this), amount);
706 messageProxy.postOutgoingMessage(
707 schainHash,
708 contractReceiver,
709 data
710 );
711 }
712
713 /**
714 * @dev Check if the receiver is in the delay whitelist
715 */
716 function isReceiverTrusted(SchainHash schainHash, address receiver) public view override returns (bool) {
717 return _delayConfig[schainHash].trustedReceivers.contains(receiver);
718 }
719
720 // private
721
722 /**
723 * @dev Tries to do N amount of ERC20 transfers
724 */
725 function _doNTransfers(
726 DelayedTransfer[] memory transfers,
727 uint256[] memory transfersIds,
728 uint256 countToTransfer
729 )
730 private
731 {
732 for (uint256 i = 0; i < countToTransfer; ++i){
733 DelayedTransfer memory transfer = transfers[i];
734 try this.doTransfer(transfer.token, transfer.receiver, transfer.amount) {
735 emit TransferSucceeded(transfersIds[i]);
736 }
737 catch {
738 emit TransferSkipped(transfersIds[i]);
739 }
740 }
741 }
742 /**
743 * @dev Saves amount of tokens that was transferred to schain.
744 */
745 function _saveTransferredAmount(SchainHash schainHash, address erc20Token, uint256 amount) private {
746 transferredAmount[schainHash][erc20Token] += amount;
747 }
748
749 /**
750 * @dev Removes amount of tokens that was transferred from schain.
751 */
752 function _removeTransferredAmount(SchainHash schainHash, address erc20Token, uint256 amount) private {
753 transferredAmount[schainHash][erc20Token] -= amount;
754 }
755
756 /**
757 * @dev Allows DepositBoxERC20 to receive ERC20 tokens.
758 *
759 * Emits an {ERC20TokenReady} event.
760 *
761 * Requirements:
762 *
763 * - Amount must be less than or equal to the total supply of the ERC20 contract.
764 * - Whitelist should be turned off for auto adding tokens to DepositBoxERC20.
765 */
766 function _receiveERC20(
767 string calldata schainName,
768 address erc20OnMainnet,
769 address to,
770 uint256 amount
771 )
772 private
773 returns (bytes memory data)
774 {
775 SchainHash schainHash = _schainHash(schainName);
776 IERC20MetadataUpgradeable erc20 = IERC20MetadataUpgradeable(erc20OnMainnet);
777 uint256 totalSupply = erc20.totalSupply();
778 require(amount <= totalSupply, "Amount is incorrect");
779 bool isERC20AddedToSchain = _schainToERC20[schainHash].contains(erc20OnMainnet);
780 if (!isERC20AddedToSchain) {
exec
/bin/bash -lc "nl -ba contracts/schain/TokenManagers/TokenManagerERC20.sol | sed -n '314,362p'" in /tmp/codex-sryvig8b
succeeded in 0ms:
314 function _exit(
315 SchainHash chainHash,
316 address messageReceiver,
317 address contractOnMainChain,
318 address to,
319 uint256 amount
320 )
321 private
322 {
323 bool isMainChainToken;
324 ERC20OnChain contractOnSchain = clonesErc20[chainHash][contractOnMainChain];
325 if (address(contractOnSchain) == address(0)) {
326 contractOnSchain = ERC20OnChain(contractOnMainChain);
327 require(!addedClones[contractOnSchain], "Incorrect main chain token");
328 isMainChainToken = true;
329 }
330 require(address(contractOnSchain).isContract(), "No token clone on schain");
331 require(contractOnSchain.balanceOf(msg.sender) >= amount, "Insufficient funds");
332 require(
333 contractOnSchain.allowance(
334 msg.sender,
335 address(this)
336 ) >= amount,
337 "Transfer is not approved by token holder"
338 );
339 bytes memory data = Messages.encodeTransferErc20Message(address(contractOnMainChain), to, amount);
340 if (isMainChainToken) {
341 require(chainHash != MAINNET_HASH, "Main chain token could not be transferred to Mainnet");
342 data = _receiveERC20(
343 chainHash,
344 address(contractOnSchain),
345 to,
346 amount
347 );
348 _saveTransferredAmount(chainHash, address(contractOnSchain), amount);
349 require(
350 contractOnSchain.transferFrom(msg.sender, address(this), amount),
351 "Transfer was failed"
352 );
353 } else {
354 require(
355 contractOnSchain.transferFrom(msg.sender, address(this), amount),
356 "Transfer was failed"
357 );
358 contractOnSchain.burn(amount);
359 }
360 messageProxy.postOutgoingMessage(
361 chainHash,
362 messageReceiver,
exec
/bin/bash -lc "rg -n \"topUpReceiverBalance\\(\" contracts -g '"'!contracts/test/**'"'" in /tmp/codex-sryvig8b
succeeded in 0ms:
contracts/schain/MessageProxyForSchain.sol:254: function topUpReceiverBalance(address payable receiver) external override {
contracts/schain/TokenManagers/TokenManagerERC20.sol:307: messageProxy.topUpReceiverBalance(payable(receiver));
contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol:123: messageProxy.topUpReceiverBalance(payable(receiver));
contracts/schain/TokenManagers/TokenManagerERC1155.sol:363: messageProxy.topUpReceiverBalance(payable(receiver));
contracts/schain/TokenManagers/TokenManagerERC1155.sol:414: messageProxy.topUpReceiverBalance(payable(receiver));
contracts/schain/TokenManagers/TokenManagerERC721.sol:252: messageProxy.topUpReceiverBalance(payable(receiver));
contracts/schain/TokenManagers/TokenManagerEth.sol:85: messageProxy.topUpReceiverBalance(payable(receiver));
exec
/bin/bash -lc "sed -n '1,220p' @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol" in /tmp/codex-sryvig8b
succeeded in 0ms:
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
exec
/bin/bash -lc "sed -n '1001,2000p' AUDIT_BUNDLE.txt" in /tmp/codex-sryvig8b
succeeded in 0ms:
interface IMessageProxyForSchain is IMessageProxy {
struct OutgoingMessageData {
SchainHash dstChainHash; // destination chain
uint256 msgCounter; // message counter
address srcContract; // origin
address dstContract; // receiver
bytes data; // payload
}
function initialize(IKeyStorage blsKeyStorage, string memory schainName) external;
function setMinimumReceiverBalance(uint256 balance) external;
function topUpReceiverBalance(address payable receiver) external;
function messageInProgress() external view returns (bool);
function verifyOutgoingMessageData(OutgoingMessageData memory message) external view returns (bool);
function verifySignature(bytes32 hashedMessage, Signature memory signature) external view returns (bool);
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/ITokenManager.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManager - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "../IMessageReceiver.sol";
interface ITokenManager is IMessageReceiver {
function enableAutomaticDeploy() external;
function addTokenManager(string calldata schainName, address newTokenManager) external;
function removeTokenManager(string calldata schainName) external;
function hasTokenManager(string calldata schainName) external view returns (bool);
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/ITokenManagerLinker.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManagerLinker - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "./IMessageProxyForSchain.sol";
import "./ITokenManager.sol";
interface ITokenManagerLinker {
function connectSchain(string calldata schainName) external;
function disconnectSchain(string calldata schainName) external;
function initialize(IMessageProxyForSchain newMessageProxyAddress, address linker) external;
function registerTokenManager(ITokenManager newTokenManager) external;
function removeTokenManager(ITokenManager tokenManagerAddress) external;
function hasSchain(string calldata schainName) external view returns (bool connected);
function hasTokenManager(address tokenManager) external view returns (bool);
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/TokenManagers/ITokenContractManager.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManagerERC20 - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "../ICommunityLocker.sol";
import "../IMessageProxyForSchain.sol";
import "../ITokenManager.sol";
import "../ITokenManagerLinker.sol";
interface ITokenContractManager is ITokenManager {
function initialize(
string memory newChainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newIMALinker,
ICommunityLocker newCommunityLocker,
address newDepositBox
) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC1155.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManagerERC1155 - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "./ITokenContractManager.sol";
interface ITokenManagerERC1155 is ITokenContractManager {
function exitToMainERC1155(
address contractOnMainnet,
uint256 id,
uint256 amount
) external;
function exitToMainERC1155Batch(
address contractOnMainnet,
uint256[] memory ids,
uint256[] memory amounts
) external;
function transferToSchainERC1155(
string calldata targetSchainName,
address contractOnMainnet,
uint256 id,
uint256 amount
) external;
function transferToSchainERC1155Batch(
string calldata targetSchainName,
address contractOnMainnet,
uint256[] memory ids,
uint256[] memory amounts
) external;
function addERC1155TokenByOwner(
string calldata targetChainName,
address erc1155OnMainnet,
address erc1155OnSchain
) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC20.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManagerERC20 - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "./ITokenContractManager.sol";
interface ITokenManagerERC20 is ITokenContractManager {
function exitToMainERC20(
address contractOnMainnet,
uint256 amount
) external;
function transferToSchainERC20(
string calldata targetSchainName,
address contractOnMainnet,
uint256 amount
) external;
function transferToSchainERC20Direct(
string calldata targetSchainName,
address contractOnMainnet,
uint256 amount,
address to
) external;
function transferToSchainHashERC20Direct(
SchainHash targetSchainHash,
address contractOnMainnet,
uint256 amount,
address receiver
) external;
function addERC20TokenByOwner(
string calldata targetChainName,
address erc20OnMainnet,
address erc20OnSchain
) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC721.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManagerERC721 - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "./ITokenContractManager.sol";
interface ITokenManagerERC721 is ITokenContractManager {
function exitToMainERC721(address contractOnMainnet, uint256 tokenId) external;
function transferToSchainERC721(
string calldata targetSchainName,
address contractOnMainnet,
uint256 tokenId
) external;
function addERC721TokenByOwner(
string calldata targetChainName,
address erc721OnMainnet,
address erc721OnSchain
) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerEth.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* ITokenManagerEth - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
import "../tokens/IEthErc20.sol";
import "../ICommunityLocker.sol";
import "../IMessageProxyForSchain.sol";
import "../ITokenManager.sol";
import "../ITokenManagerLinker.sol";
interface ITokenManagerEth is ITokenManager {
function initialize(
string memory newChainName,
IMessageProxyForSchain newMessageProxy,
ITokenManagerLinker newIMALinker,
ICommunityLocker newCommunityLocker,
address newDepositBox,
IEthErc20 ethErc20Address
) external;
function setEthErc20Address(IEthErc20 newEthErc20Address) external;
function exitToMain(uint256 amount) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/bls/IFieldOperations.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* IFieldOperations.sol - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
interface IFieldOperations {
/**
* @dev Structure that represents the field element { a + ib }
*/
struct Fp2Point {
uint a;
uint b;
}
/**
* @dev Structure that represents an element of G2
*/
struct G2Point {
Fp2Point x;
Fp2Point y;
}
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/tokens/IERC1155OnChain.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* IERC1155OnChain - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
interface IERC1155OnChain {
function mint(
address account,
uint256 id,
uint256 amount,
bytes memory data
) external;
function mintBatch(
address account,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/tokens/IERC20OnChain.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* IERC20OnChain - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
interface IERC20OnChain {
function mint(address account, uint256 value) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/tokens/IERC721OnChain.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* IERC721OnChain - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
interface IERC721OnChain {
function setTokenURI(uint256 tokenId, string calldata tokenUri) external returns (bool);
function mint(address account, uint256 tokenId) external;
}
================================================================================
FILE: @skalenetwork/ima-interfaces/schain/tokens/IEthErc20.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/**
* IEthErc20 - SKALE Interchain Messaging Agent
* Copyright (C) 2021-Present SKALE Labs
* @author Dmytro Stebaiev
*
* SKALE IMA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SKALE IMA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SKALE IMA. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.8.19 <0.9.0;
interface IEthErc20 {
function mint(address account, uint256 amount) external;
function forceBurn(address account, uint256 amount) external;
function initialize(address tokenManagerEthAddress) external;
}
================================================================================
FILE: @skalenetwork/skale-manager-interfaces/IContractManager.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/*
IContractManager.sol - SKALE Manager Interfaces
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaeiv
SKALE Manager Interfaces is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager Interfaces is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager Interfaces. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.6.10 <0.9.0;
interface IContractManager {
/**
* @dev Emitted when contract is upgraded.
*/
event ContractUpgraded(string contractsName, address contractsAddress);
function initialize() external;
function setContractsAddress(string calldata contractsName, address newContractsAddress) external;
function contracts(bytes32 nameHash) external view returns (address);
function getDelegationPeriodManager() external view returns (address);
function getBounty() external view returns (address);
function getValidatorService() external view returns (address);
function getTimeHelpers() external view returns (address);
function getConstantsHolder() external view returns (address);
function getSkaleToken() external view returns (address);
function getTokenState() external view returns (address);
function getPunisher() external view returns (address);
function getContract(string calldata name) external view returns (address);
}
================================================================================
FILE: @skalenetwork/skale-manager-interfaces/INodes.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/*
INodes.sol - SKALE Manager
Copyright (C) 2018-Present SKALE Labs
@author Artem Payvin
SKALE Manager is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.6.10 <0.9.0;
import "./utils/IRandom.sol";
interface INodes {
// All Nodes states
enum NodeStatus {Active, Leaving, Left, In_Maintenance}
struct Node {
string name;
bytes4 ip;
bytes4 publicIP;
uint16 port;
bytes32[2] publicKey;
uint startBlock;
uint lastRewardDate;
uint finishTime;
NodeStatus status;
uint validatorId;
}
// struct to note which Nodes and which number of Nodes owned by user
struct CreatedNodes {
mapping (uint => bool) isNodeExist;
uint numberOfNodes;
}
struct SpaceManaging {
uint8 freeSpace;
uint indexInSpaceMap;
}
struct NodeCreationParams {
string name;
bytes4 ip;
bytes4 publicIp;
uint16 port;
bytes32[2] publicKey;
uint16 nonce;
string domainName;
}
/**
* @dev Emitted when a node is created.
*/
event NodeCreated(
uint nodeIndex,
address owner,
string name,
bytes4 ip,
bytes4 publicIP,
uint16 port,
uint16 nonce,
string domainName
);
/**
* @dev Emitted when a node completes a network exit.
*/
event ExitCompleted(
uint nodeIndex
);
/**
* @dev Emitted when a node begins to exit from the network.
*/
event ExitInitialized(
uint nodeIndex,
uint startLeavingPeriod
);
/**
* @dev Emitted when a node set to in compliant or compliant.
*/
event IncompliantNode(
uint indexed nodeIndex,
bool status
);
/**
* @dev Emitted when a node set to in maintenance or from in maintenance.
*/
event MaintenanceNode(
uint indexed nodeIndex,
bool status
);
/**
* @dev Emitted when a node status changed.
*/
event IPChanged(
uint indexed nodeIndex,
bytes4 previousIP,
bytes4 newIP
);
function removeSpaceFromNode(uint nodeIndex, uint8 space) external returns (bool);
function addSpaceToNode(uint nodeIndex, uint8 space) external;
function changeNodeLastRewardDate(uint nodeIndex) external;
function changeNodeFinishTime(uint nodeIndex, uint time) external;
function createNode(address from, NodeCreationParams calldata params) external;
function initExit(uint nodeIndex) external;
function completeExit(uint nodeIndex) external returns (bool);
function deleteNodeForValidator(uint validatorId, uint nodeIndex) external;
function checkPossibilityCreatingNode(address nodeAddress) external;
function checkPossibilityToMaintainNode(uint validatorId, uint nodeIndex) external returns (bool);
function setNodeInMaintenance(uint nodeIndex) external;
function removeNodeFromInMaintenance(uint nodeIndex) external;
function setNodeIncompliant(uint nodeIndex) external;
function setNodeCompliant(uint nodeIndex) external;
function setDomainName(uint nodeIndex, string memory domainName) external;
function makeNodeVisible(uint nodeIndex) external;
function makeNodeInvisible(uint nodeIndex) external;
function changeIP(uint nodeIndex, bytes4 newIP, bytes4 newPublicIP) external;
function numberOfActiveNodes() external view returns (uint);
function incompliant(uint nodeIndex) external view returns (bool);
function getRandomNodeWithFreeSpace(
uint8 freeSpace,
IRandom.RandomGenerator memory randomGenerator
)
external
view
returns (uint);
function isTimeForReward(uint nodeIndex) external view returns (bool);
function getNodeIP(uint nodeIndex) external view returns (bytes4);
function getNodeDomainName(uint nodeIndex) external view returns (string memory);
function getNodePort(uint nodeIndex) external view returns (uint16);
function getNodePublicKey(uint nodeIndex) external view returns (bytes32[2] memory);
function getNodeAddress(uint nodeIndex) external view returns (address);
function getNodeFinishTime(uint nodeIndex) external view returns (uint);
function isNodeLeft(uint nodeIndex) external view returns (bool);
function isNodeInMaintenance(uint nodeIndex) external view returns (bool);
function getNodeLastRewardDate(uint nodeIndex) external view returns (uint);
function getNodeNextRewardDate(uint nodeIndex) external view returns (uint);
function getNumberOfNodes() external view returns (uint);
function getNumberOnlineNodes() external view returns (uint);
function getActiveNodeIds() external view returns (uint[] memory activeNodeIds);
function getNodeStatus(uint nodeIndex) external view returns (NodeStatus);
function getValidatorNodeIndexes(uint validatorId) external view returns (uint[] memory);
function countNodesWithFreeSpace(uint8 freeSpace) external view returns (uint count);
function getValidatorId(uint nodeIndex) external view returns (uint);
function isNodeExist(address from, uint nodeIndex) external view returns (bool);
function isNodeActive(uint nodeIndex) external view returns (bool);
function isNodeLeaving(uint nodeIndex) external view returns (bool);
}
================================================================================
FILE: @skalenetwork/skale-manager-interfaces/ISchains.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/*
ISchains.sol - SKALE Manager Interfaces
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaeiv
SKALE Manager Interfaces is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager Interfaces is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager Interfaces. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.6.10 <0.9.0;
interface ISchains {
struct SchainOption {
string name;
bytes value;
}
/**
* @dev Emitted when an schain is created.
*/
event SchainCreated(
string name,
address owner,
uint partOfNode,
uint lifetime,
uint numberOfNodes,
uint deposit,
uint16 nonce,
bytes32 schainHash
);
/**
* @dev Emitted when an schain is deleted.
*/
event SchainDeleted(
address owner,
string name,
bytes32 indexed schainHash
);
/**
* @dev Emitted when a node in an schain is rotated.
*/
event NodeRotated(
bytes32 schainHash,
uint oldNode,
uint newNode
);
/**
* @dev Emitted when a node is added to an schain.
*/
event NodeAdded(
bytes32 schainHash,
uint newNode
);
/**
* @dev Emitted when a group of nodes is created for an schain.
*/
event SchainNodes(
string name,
bytes32 schainHash,
uint[] nodesInGroup
);
function addSchain(address from, uint deposit, bytes calldata data) external;
function addSchainByFoundation(
uint lifetime,
uint8 typeOfSchain,
uint16 nonce,
string calldata name,
address schainOwner,
address schainOriginator,
SchainOption[] calldata options
)
external
payable;
function deleteSchain(address from, string calldata name) external;
function deleteSchainByRoot(string calldata name) external;
function restartSchainCreation(string calldata name) external;
function verifySchainSignature(
uint256 signA,
uint256 signB,
bytes32 hash,
uint256 counter,
uint256 hashA,
uint256 hashB,
string calldata schainName
)
external
view
returns (bool);
function getSchainPrice(uint typeOfSchain, uint lifetime) external view returns (uint);
function getOption(bytes32 schainHash, string calldata optionName) external view returns (bytes memory);
function getOptions(bytes32 schainHash) external view returns (SchainOption[] memory);
}
================================================================================
FILE: @skalenetwork/skale-manager-interfaces/ISchainsInternal.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/*
ISchainsInternal - SKALE Manager Interfaces
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaeiv
SKALE Manager Interfaces is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager Interfaces is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager Interfaces. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.6.10 <0.9.0;
import "./INodes.sol";
interface ISchainsInternal {
struct Schain {
string name;
address owner;
uint indexInOwnerList;
uint8 partOfNode;
uint lifetime;
uint startDate;
uint startBlock;
uint deposit;
uint64 index;
uint generation;
address originator;
}
struct SchainType {
uint8 partOfNode;
uint numberOfNodes;
}
/**
* @dev Emitted when schain type added.
*/
event SchainTypeAdded(uint indexed schainType, uint partOfNode, uint numberOfNodes);
/**
* @dev Emitted when schain type removed.
*/
event SchainTypeRemoved(uint indexed schainType);
function initializeSchain(
string calldata name,
address from,
address originator,
uint lifetime,
uint deposit) external;
function createGroupForSchain(
bytes32 schainHash,
uint numberOfNodes,
uint8 partOfNode
)
external
returns (uint[] memory);
function changeLifetime(bytes32 schainHash, uint lifetime, uint deposit) external;
function removeSchain(bytes32 schainHash, address from) external;
function removeNodeFromSchain(uint nodeIndex, bytes32 schainHash) external;
function deleteGroup(bytes32 schainHash) external;
function setException(bytes32 schainHash, uint nodeIndex) external;
function setNodeInGroup(bytes32 schainHash, uint nodeIndex) external;
function removeHolesForSchain(bytes32 schainHash) external;
function addSchainType(uint8 partOfNode, uint numberOfNodes) external;
function removeSchainType(uint typeOfSchain) external;
function setNumberOfSchainTypes(uint newNumberOfSchainTypes) external;
function removeNodeFromAllExceptionSchains(uint nodeIndex) external;
function removeAllNodesFromSchainExceptions(bytes32 schainHash) external;
function makeSchainNodesInvisible(bytes32 schainHash) external;
function makeSchainNodesVisible(bytes32 schainHash) external;
function newGeneration() external;
function addSchainForNode(INodes nodes,uint nodeIndex, bytes32 schainHash) external;
function removeSchainForNode(uint nodeIndex, uint schainIndex) external;
function removeNodeFromExceptions(bytes32 schainHash, uint nodeIndex) external;
function isSchainActive(bytes32 schainHash) external view returns (bool);
function schainsAtSystem(uint index) external view returns (bytes32);
function numberOfSchains() external view returns (uint64);
function getSchains() external view returns (bytes32[] memory);
function getSchainsPartOfNode(bytes32 schainHash) external view returns (uint8);
function getSchainListSize(address from) external view returns (uint);
function getSchainHashesByAddress(address from) external view returns (bytes32[] memory);
function getSchainHashesForNode(uint nodeIndex) external view returns (bytes32[] memory);
function getSchainOwner(bytes32 schainHash) external view returns (address);
function getSchainOriginator(bytes32 schainHash) external view returns (address);
function isSchainNameAvailable(string calldata name) external view returns (bool);
function isTimeExpired(bytes32 schainHash) external view returns (bool);
function isOwnerAddress(address from, bytes32 schainHash) external view returns (bool);
function getSchainName(bytes32 schainHash) external view returns (string memory);
function getActiveSchain(uint nodeIndex) external view returns (bytes32);
function getActiveSchains(uint nodeIndex) external view returns (bytes32[] memory activeSchains);
function getNumberOfNodesInGroup(bytes32 schainHash) external view returns (uint);
function getNodesInGroup(bytes32 schainHash) external view returns (uint[] memory);
function isNodeAddressesInGroup(bytes32 schainHash, address sender) external view returns (bool);
function getNodeIndexInGroup(bytes32 schainHash, uint nodeHash) external view returns (uint);
function isAnyFreeNode(bytes32 schainHash) external view returns (bool);
function checkException(bytes32 schainHash, uint nodeIndex) external view returns (bool);
function checkHoleForSchain(bytes32 schainHash, uint indexOfNode) external view returns (bool);
function checkSchainOnNode(uint nodeIndex, bytes32 schainHash) external view returns (bool);
function getSchainType(uint typeOfSchain) external view returns(uint8, uint);
function getGeneration(bytes32 schainHash) external view returns (uint);
function isSchainExist(bytes32 schainHash) external view returns (bool);
}
================================================================================
FILE: @skalenetwork/skale-manager-interfaces/IWallets.sol
================================================================================
// SPDX-License-Identifier: AGPL-3.0-only
/*
IWallets - SKALE Manager Interfaces
Copyright (C) 2021-Present SKALE Labs
@author Dmytro Stebaeiv
SKALE Manager Interfaces is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SKALE Manager Interfaces is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with SKALE Manager Interfaces. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.6.10 <0.9.0;
interface IWallets {
receive() external payable;
function refundGasByValidator(uint validatorId, address payable spender, uint gasLimit) external;
function refundGasByValidatorToSchain(uint validatorId, bytes32 schainHash) external;
I’ve traced the bridge/accounting paths on mainnet and schain side. Two concrete loss-of-funds paths are standing out: ERC20 amount accounting trusts nominal transfers, and delayed ERC20 payouts clear claims before confirming token delivery.
✓ Read AUDIT_BUNDLE.txt completely and map first-party contracts plus trust boundaries
→ Inspect high-risk flows: message verification, token/ETH deposit-withdraw paths, external calls, and upgradeable init/access patterns
• Assemble concrete exploit findings with file/line references and emit JSON
Findings are assembled. I’m formatting the final audit output as schema-valid JSON now.
✓ Read AUDIT_BUNDLE.txt completely and map first-party contracts plus trust boundaries
✓ Inspect high-risk flows: message verification, token/ETH deposit-withdraw paths, external calls, and upgradeable init/access patterns
→ Assemble concrete exploit findings with file/line references and emit JSON
codex
{"no_findings":false,"summary":"Found a high-severity ERC20 accounting break on lock, a medium-severity delayed-withdrawal claim-loss bug, and a low-severity unauthenticated oracle setter.","findings":[{"severity":"high","category":"other","title":"ERC20 bridge accounting trusts the requested amount instead of the amount actually received","exploit_scenario":"A user bridges a fee-on-transfer or deflationary ERC20. `DepositBoxERC20` records and messages the full `amount` before/without checking how many tokens the bridge actually received. The destination chain credits the full amount, but the source bridge locked less. The attacker can later exit the full credited balance and drain other users' liquidity or leave the bridge permanently undercollateralized. The same nominal-amount assumption exists in the schain-native ERC20 path when a token is locked for schain-to-schain transfer.","recommendation":"Measure `balanceBefore`/`balanceAfter` around every ERC20 pull and bridge only the actual received amount. Revert if the received amount is smaller than requested unless the token type is explicitly unsupported. Apply the same balance-delta accounting anywhere ERC20s are locked rather than burned.","evidence":"On mainnet, the code builds the outbound message and increments `transferredAmount` using the caller-supplied `amount`, then performs `safeTransferFrom` with no balance-delta check. On schain-native ERC20 transfers, `_saveTransferredAmount(..., amount)` is also done before `transferFrom`, again assuming the nominal amount was received.","locations":["contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:698","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:704","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:705","contracts/schain/TokenManagers/TokenManagerERC20.sol:339","contracts/schain/TokenManagers/TokenManagerERC20.sol:348","contracts/schain/TokenManagers/TokenManagerERC20.sol:350"]},{"severity":"medium","category":"other","title":"Delayed ERC20 withdrawals clear user claims before confirming token delivery","exploit_scenario":"When a delayed transfer becomes withdrawable, `retrieveFor` marks it completed or deletes it from the queue before attempting the ERC20 transfer. If the token transfer then fails, the call is swallowed and only `TransferSkipped` is emitted. A token admin can pause or blacklist transfers right before unlock, or a nonstandard token can fail transfer, causing the receiver's claim to be irreversibly erased while the tokens remain stuck in the bridge contract.","recommendation":"Do not mutate delayed-transfer state until the token transfer succeeds. Revert failed payouts, or leave the transfer pending so the user can retry later. If partial progress is needed, persist an explicit failed state with an admin/user recovery path instead of deleting the claim.","evidence":"`retrieveFor` removes or marks transfers as `COMPLETED` before calling `_doNTransfers`. `_doNTransfers` catches transfer failures and only emits `TransferSkipped`, without restoring the queue entry or status.","locations":["contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:631","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:635","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:651","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:734","contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:737"]},{"severity":"low","category":"oracle","title":"`CommunityLocker.setGasPrice` accepts arbitrary caller-supplied oracle values","exploit_scenario":"Any account can update `mainnetGasPrice` and `gasPriceTimestamp` by calling `setGasPrice`; the signature parameter is unused and the verification check is commented out. Today this state is not consumed elsewhere in first-party code, so impact is limited, but if operators or future upgrades rely on it, an attacker can feed arbitrary prices and timestamps.","recommendation":"Require a verified signature or strict role-based authorization before updating oracle state. If the oracle is not live yet, disable the entrypoint rather than accepting unauthenticated writes.","evidence":"The function has no access-control modifier, the signature argument is unnamed/unused, and the intended `messageProxy.verifySignature(...)` check is commented out.","locations":["contracts/schain/CommunityLocker.sol:252","contracts/schain/CommunityLocker.sol:257","contracts/schain/CommunityLocker.sol:262","contracts/schain/CommunityLocker.sol:272"]}]}
tokens used
616,442
{
"codex": {
"ran_at": "2026-04-04T04:25:38.615660+00:00",
"returncode": 0
},
"project": {
"mode": "source",
"file_count": 143,
"import_count": 168,
"first_party_contracts_count": 105
},
"summary": "Found a high-severity ERC20 accounting break on lock, a medium-severity delayed-withdrawal claim-loss bug, and a low-severity unauthenticated oracle setter.",
"raw_final": {
"summary": "Found a high-severity ERC20 accounting break on lock, a medium-severity delayed-withdrawal claim-loss bug, and a low-severity unauthenticated oracle setter.",
"findings": [
{
"title": "ERC20 bridge accounting trusts the requested amount instead of the amount actually received",
"category": "other",
"evidence": "On mainnet, the code builds the outbound message and increments `transferredAmount` using the caller-supplied `amount`, then performs `safeTransferFrom` with no balance-delta check. On schain-native ERC20 transfers, `_saveTransferredAmount(..., amount)` is also done before `transferFrom`, again assuming the nominal amount was received.",
"severity": "high",
"locations": [
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:698",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:704",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:705",
"contracts/schain/TokenManagers/TokenManagerERC20.sol:339",
"contracts/schain/TokenManagers/TokenManagerERC20.sol:348",
"contracts/schain/TokenManagers/TokenManagerERC20.sol:350"
],
"recommendation": "Measure `balanceBefore`/`balanceAfter` around every ERC20 pull and bridge only the actual received amount. Revert if the received amount is smaller than requested unless the token type is explicitly unsupported. Apply the same balance-delta accounting anywhere ERC20s are locked rather than burned.",
"exploit_scenario": "A user bridges a fee-on-transfer or deflationary ERC20. `DepositBoxERC20` records and messages the full `amount` before/without checking how many tokens the bridge actually received. The destination chain credits the full amount, but the source bridge locked less. The attacker can later exit the full credited balance and drain other users' liquidity or leave the bridge permanently undercollateralized. The same nominal-amount assumption exists in the schain-native ERC20 path when a token is locked for schain-to-schain transfer."
},
{
"title": "Delayed ERC20 withdrawals clear user claims before confirming token delivery",
"category": "other",
"evidence": "`retrieveFor` removes or marks transfers as `COMPLETED` before calling `_doNTransfers`. `_doNTransfers` catches transfer failures and only emits `TransferSkipped`, without restoring the queue entry or status.",
"severity": "medium",
"locations": [
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:631",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:635",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:651",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:734",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:737"
],
"recommendation": "Do not mutate delayed-transfer state until the token transfer succeeds. Revert failed payouts, or leave the transfer pending so the user can retry later. If partial progress is needed, persist an explicit failed state with an admin/user recovery path instead of deleting the claim.",
"exploit_scenario": "When a delayed transfer becomes withdrawable, `retrieveFor` marks it completed or deletes it from the queue before attempting the ERC20 transfer. If the token transfer then fails, the call is swallowed and only `TransferSkipped` is emitted. A token admin can pause or blacklist transfers right before unlock, or a nonstandard token can fail transfer, causing the receiver's claim to be irreversibly erased while the tokens remain stuck in the bridge contract."
},
{
"title": "`CommunityLocker.setGasPrice` accepts arbitrary caller-supplied oracle values",
"category": "oracle",
"evidence": "The function has no access-control modifier, the signature argument is unnamed/unused, and the intended `messageProxy.verifySignature(...)` check is commented out.",
"severity": "low",
"locations": [
"contracts/schain/CommunityLocker.sol:252",
"contracts/schain/CommunityLocker.sol:257",
"contracts/schain/CommunityLocker.sol:262",
"contracts/schain/CommunityLocker.sol:272"
],
"recommendation": "Require a verified signature or strict role-based authorization before updating oracle state. If the oracle is not live yet, disable the entrypoint rather than accepting unauthenticated writes.",
"exploit_scenario": "Any account can update `mainnetGasPrice` and `gasPriceTimestamp` by calling `setGasPrice`; the signature parameter is unused and the verification check is commented out. Today this state is not consumed elsewhere in first-party code, so impact is limited, but if operators or future upgrades rely on it, an attacker can feed arbitrary prices and timestamps."
}
],
"no_findings": false
},
"no_findings": false,
"schema_version": 1
}
00000000: PUSH1 0x80 00000002: PUSH1 0x40 00000004: MSTORE 00000005: PUSH1 0x04 00000007: CALLDATASIZE 00000008: LT 00000009: PUSH2 0x020f 0000000c: JUMPI 0000000d: PUSH1 0x00 0000000f: CALLDATALOAD 00000010: PUSH1 0xe0 00000012: SHR 00000013: DUP1 00000014: PUSH4 0x6cfc7d64 00000019: GT 0000001a: PUSH2 0x0118 0000001d: JUMPI 0000001e: DUP1 0000001f: PUSH4 0xb0cba84e 00000024: GT 00000025: PUSH2 0x00a0 00000028: JUMPI 00000029: DUP1 0000002a: PUSH4 0xc80493cf 0000002f: GT 00000030: PUSH2 0x006f 00000033: JUMPI 00000034: DUP1 00000035: PUSH4 0xc80493cf 0000003a: EQ 0000003b: PUSH2 0x0667 0000003e: JUMPI 0000003f: DUP1 00000040: PUSH4 0xca15c873 00000045: EQ 00000046: PUSH2 0x0689 00000049: JUMPI 0000004a: DUP1 0000004b: PUSH4 0xd547741f 00000050: EQ 00000051: PUSH2 0x06a9 00000054: JUMPI 00000055: DUP1 00000056: PUSH4 0xe91d6390 0000005b: EQ 0000005c: PUSH2 0x06c9 0000005f: JUMPI 00000060: DUP1 00000061: PUSH4 0xff55cd40 00000066: EQ 00000067: PUSH2 0x06df 0000006a: JUMPI 0000006b: PUSH1 0x00 0000006d: DUP1 0000006e: REVERT 0000006f: JUMPDEST 00000070: DUP1 00000071: PUSH4 0xb0cba84e 00000076: EQ 00000077: PUSH2 0x05d3 0000007a: JUMPI 0000007b: DUP1 0000007c: PUSH4 0xbbc4e8c2 00000081: EQ 00000082: PUSH2 0x05f3 00000085: JUMPI 00000086: DUP1 00000087: PUSH4 0xc0c53b8b 0000008c: EQ 0000008d: PUSH2 0x0627 00000090: JUMPI 00000091: DUP1 00000092: PUSH4 0xc4d66de8 00000097: EQ 00000098: PUSH2 0x0647 0000009b: JUMPI 0000009c: PUSH1 0x00 0000009e: DUP1 0000009f: REVERT 000000a0: JUMPDEST 000000a1: DUP1 000000a2: PUSH4 0x91d14854 000000a7: GT 000000a8: PUSH2 0x00e7 000000ab: JUMPI 000000ac: DUP1 000000ad: PUSH4 0x91d14854 000000b2: EQ 000000b3: PUSH2 0x0548 000000b6: JUMPI 000000b7: DUP1 000000b8: PUSH4 0x9769b439 000000bd: EQ 000000be: PUSH2 0x0568 000000c1: JUMPI 000000c2: DUP1 000000c3: PUSH4 0x9bb2a2dd 000000c8: EQ 000000c9: PUSH2 0x0588 000000cc: JUMPI 000000cd: DUP1 000000ce: PUSH4 0xa217fddf 000000d3: EQ 000000d4: PUSH2 0x059e 000000d7: JUMPI 000000d8: DUP1 000000d9: PUSH4 0xa69cc360 000000de: EQ 000000df: PUSH2 0x05b3 000000e2: JUMPI 000000e3: PUSH1 0x00 000000e5: DUP1 000000e6: REVERT 000000e7: JUMPDEST 000000e8: DUP1 000000e9: PUSH4 0x6cfc7d64 000000ee: EQ 000000ef: PUSH2 0x0497 000000f2: JUMPI 000000f3: DUP1 000000f4: PUSH4 0x7259c116 000000f9: EQ 000000fa: PUSH2 0x04cd 000000fd: JUMPI 000000fe: DUP1 000000ff: PUSH4 0x86c051eb 00000104: EQ 00000105: PUSH2 0x04ed 00000108: JUMPI 00000109: DUP1 0000010a: PUSH4 0x9010d07c 0000010f: EQ 00000110: PUSH2 0x0528 00000113: JUMPI 00000114: PUSH1 0x00 00000116: DUP1 00000117: REVERT 00000118: JUMPDEST 00000119: DUP1 0000011a: PUSH4 0x36568abe 0000011f: GT 00000120: PUSH2 0x019b 00000123: JUMPI 00000124: DUP1 00000125: PUSH4 0x4e9e82b3 0000012a: GT 0000012b: PUSH2 0x016a 0000012e: JUMPI 0000012f: DUP1 00000130: PUSH4 0x4e9e82b3 00000135: EQ 00000136: PUSH2 0x03f7 00000139: JUMPI 0000013a: DUP1 0000013b: PUSH4 0x5573b8b6 00000140: EQ 00000141: PUSH2 0x0417 00000144: JUMPI 00000145: DUP1 00000146: PUSH4 0x5c75f49d 0000014b: EQ 0000014c: PUSH2 0x0437 0000014f: JUMPI 00000150: DUP1 00000151: PUSH4 0x5fc1eba3 00000156: EQ 00000157: PUSH2 0x0457 0000015a: JUMPI 0000015b: DUP1 0000015c: PUSH4 0x64f8ebd9 00000161: EQ 00000162: PUSH2 0x0477 00000165: JUMPI 00000166: PUSH1 0x00 00000168: DUP1 00000169: REVERT 0000016a: JUMPDEST 0000016b: DUP1 0000016c: PUSH4 0x36568abe 00000171: EQ 00000172: PUSH2 0x035f 00000175: JUMPI 00000176: DUP1 00000177: PUSH4 0x410ec2e2 0000017c: EQ 0000017d: PUSH2 0x037f 00000180: JUMPI 00000181: DUP1 00000182: PUSH4 0x468eaa29 00000187: EQ 00000188: PUSH2 0x03b7 0000018b: JUMPI 0000018c: DUP1 0000018d: PUSH4 0x485cc955 00000192: EQ 00000193: PUSH2 0x03d7 00000196: JUMPI 00000197: PUSH1 0x00 00000199: DUP1 0000019a: REVERT 0000019b: JUMPDEST 0000019c: DUP1 0000019d: PUSH4 0x23dc68d1 000001a2: GT 000001a3: PUSH2 0x01e2 000001a6: JUMPI 000001a7: DUP1 000001a8: PUSH4 0x23dc68d1 000001ad: EQ 000001ae: PUSH2 0x02ad 000001b1: JUMPI 000001b2: DUP1 000001b3: PUSH4 0x241827dc 000001b8: EQ 000001b9: PUSH2 0x02cf 000001bc: JUMPI 000001bd: DUP1 000001be: PUSH4 0x248a9ca3 000001c3: EQ 000001c4: PUSH2 0x02ef 000001c7: JUMPI 000001c8: DUP1 000001c9: PUSH4 0x2f2ff15d 000001ce: EQ 000001cf: PUSH2 0x031f 000001d2: JUMPI 000001d3: DUP1 000001d4: PUSH4 0x333271d0 000001d9: EQ 000001da: PUSH2 0x033f 000001dd: JUMPI 000001de: PUSH1 0x00 000001e0: DUP1 000001e1: REVERT 000001e2: JUMPDEST 000001e3: DUP1 000001e4: PUSH4 0x01ffc9a7 000001e9: EQ 000001ea: PUSH2 0x0214 000001ed: JUMPI 000001ee: DUP1 000001ef: PUSH4 0x096ae28c 000001f4: EQ 000001f5: PUSH2 0x0249 000001f8: JUMPI 000001f9: DUP1 000001fa: PUSH4 0x1bc29a76 000001ff: EQ 00000200: PUSH2 0x026d 00000203: JUMPI 00000204: DUP1 00000205: PUSH4 0x1dd7cecf 0000020a: EQ 0000020b: PUSH2 0x028d 0000020e: JUMPI 0000020f: JUMPDEST 00000210: PUSH1 0x00 00000212: DUP1 00000213: REVERT 00000214: JUMPDEST 00000215: CALLVALUE 00000216: DUP1 00000217: ISZERO 00000218: PUSH2 0x0220 0000021b: JUMPI 0000021c: PUSH1 0x00 0000021e: DUP1 0000021f: REVERT 00000220: JUMPDEST 00000221: POP 00000222: PUSH2 0x0234 00000225: PUSH2 0x022f 00000228: CALLDATASIZE 00000229: PUSH1 0x04 0000022b: PUSH2 0x23e0 0000022e: JUMP 0000022f: JUMPDEST 00000230: PUSH2 0x06f2 00000233: JUMP 00000234: JUMPDEST 00000235: PUSH1 0x40 00000237: MLOAD 00000238: SWAP1 00000239: ISZERO 0000023a: ISZERO 0000023b: DUP2 0000023c: MSTORE 0000023d: PUSH1 0x20 0000023f: ADD 00000240: JUMPDEST 00000241: PUSH1 0x40 00000243: MLOAD 00000244: DUP1 00000245: SWAP2 00000246: SUB 00000247: SWAP1 00000248: RETURN 00000249: JUMPDEST 0000024a: CALLVALUE 0000024b: DUP1 0000024c: ISZERO 0000024d: PUSH2 0x0255 00000250: JUMPI 00000251: PUSH1 0x00 00000253: DUP1 00000254: REVERT 00000255: JUMPDEST 00000256: POP 00000257: PUSH2 0x025f 0000025a: PUSH1 0xd0 0000025c: SLOAD 0000025d: DUP2 0000025e: JUMP 0000025f: JUMPDEST 00000260: PUSH1 0x40 00000262: MLOAD 00000263: SWAP1 00000264: DUP2 00000265: MSTORE 00000266: PUSH1 0x20 00000268: ADD 00000269: PUSH2 0x0240 0000026c: JUMP 0000026d: JUMPDEST 0000026e: CALLVALUE 0000026f: DUP1 00000270: ISZERO 00000271: PUSH2 0x0279 00000274: JUMPI 00000275: PUSH1 0x00 00000277: DUP1 00000278: REVERT 00000279: JUMPDEST 0000027a: POP 0000027b: PUSH2 0x0234 0000027e: PUSH2 0x0288 00000281: CALLDATASIZE 00000282: PUSH1 0x04 00000284: PUSH2 0x241f 00000287: JUMP 00000288: JUMPDEST 00000289: PUSH2 0x071d 0000028c: JUMP 0000028d: JUMPDEST 0000028e: CALLVALUE 0000028f: DUP1 00000290: ISZERO 00000291: PUSH2 0x0299 00000294: JUMPI 00000295: PUSH1 0x00 00000297: DUP1 00000298: REVERT 00000299: JUMPDEST 0000029a: POP 0000029b: PUSH2 0x025f 0000029e: PUSH2 0x02a8 000002a1: CALLDATASIZE 000002a2: PUSH1 0x04 000002a4: PUSH2 0x24a0 000002a7: JUMP 000002a8: JUMPDEST 000002a9: PUSH2 0x0886 000002ac: JUMP 000002ad: JUMPDEST 000002ae: CALLVALUE 000002af: DUP1 000002b0: ISZERO 000002b1: PUSH2 0x02b9 000002b4: JUMPI 000002b5: PUSH1 0x00 000002b7: DUP1 000002b8: REVERT 000002b9: JUMPDEST 000002ba: POP 000002bb: PUSH2 0x02cd 000002be: PUSH2 0x02c8 000002c1: CALLDATASIZE 000002c2: PUSH1 0x04 000002c4: PUSH2 0x24f5 000002c7: JUMP 000002c8: JUMPDEST 000002c9: PUSH2 0x08f5 000002cc: JUMP 000002cd: JUMPDEST 000002ce: STOP 000002cf: JUMPDEST 000002d0: CALLVALUE 000002d1: DUP1 000002d2: ISZERO 000002d3: PUSH2 0x02db 000002d6: JUMPI 000002d7: PUSH1 0x00 000002d9: DUP1 000002da: REVERT 000002db: JUMPDEST 000002dc: POP 000002dd: PUSH2 0x0234 000002e0: PUSH2 0x02ea 000002e3: CALLDATASIZE 000002e4: PUSH1 0x04 000002e6: PUSH2 0x254c 000002e9: JUMP 000002ea: JUMPDEST 000002eb: PUSH2 0x0aa8 000002ee: JUMP 000002ef: JUMPDEST 000002f0: CALLVALUE 000002f1: DUP1 000002f2: ISZERO 000002f3: PUSH2 0x02fb 000002f6: JUMPI 000002f7: PUSH1 0x00 000002f9: DUP1 000002fa: REVERT 000002fb: JUMPDEST 000002fc: POP 000002fd: PUSH2 0x025f 00000300: PUSH2 0x030a 00000303: CALLDATASIZE 00000304: PUSH1 0x04 00000306: PUSH2 0x257c 00000309: JUMP 0000030a: JUMPDEST 0000030b: PUSH1 0x00 0000030d: SWAP1 0000030e: DUP2 0000030f: MSTORE 00000310: PUSH1 0x65 00000312: PUSH1 0x20 00000314: MSTORE 00000315: PUSH1 0x40 00000317: SWAP1 00000318: KECCAK256 00000319: PUSH1 0x01 0000031b: ADD 0000031c: SLOAD 0000031d: SWAP1 0000031e: JUMP 0000031f: JUMPDEST 00000320: CALLVALUE 00000321: DUP1 00000322: ISZERO 00000323: PUSH2 0x032b 00000326: JUMPI 00000327: PUSH1 0x00 00000329: DUP1 0000032a: REVERT 0000032b: JUMPDEST 0000032c: POP 0000032d: PUSH2 0x02cd 00000330: PUSH2 0x033a 00000333: CALLDATASIZE 00000334: PUSH1 0x04 00000336: PUSH2 0x254c 00000339: JUMP 0000033a: JUMPDEST 0000033b: PUSH2 0x0ae9 0000033e: JUMP 0000033f: JUMPDEST 00000340: CALLVALUE 00000341: DUP1 00000342: ISZERO 00000343: PUSH2 0x034b 00000346: JUMPI 00000347: PUSH1 0x00 00000349: DUP1 0000034a: REVERT 0000034b: JUMPDEST 0000034c: POP 0000034d: PUSH2 0x02cd 00000350: PUSH2 0x035a 00000353: CALLDATASIZE 00000354: PUSH1 0x04 00000356: PUSH2 0x2595 00000359: JUMP 0000035a: JUMPDEST 0000035b: PUSH2 0x0b13 0000035e: JUMP 0000035f: JUMPDEST 00000360: CALLVALUE 00000361: DUP1 00000362: ISZERO 00000363: PUSH2 0x036b 00000366: JUMPI 00000367: PUSH1 0x00 00000369: DUP1 0000036a: REVERT 0000036b: JUMPDEST 0000036c: POP 0000036d: PUSH2 0x02cd 00000370: PUSH2 0x037a 00000373: CALLDATASIZE 00000374: PUSH1 0x04 00000376: PUSH2 0x254c 00000379: JUMP 0000037a: JUMPDEST 0000037b: PUSH2 0x0c24 0000037e: JUMP 0000037f: JUMPDEST 00000380: CALLVALUE 00000381: DUP1 00000382: ISZERO 00000383: PUSH2 0x038b 00000386: JUMPI 00000387: PUSH1 0x00 00000389: DUP1 0000038a: REVERT 0000038b: JUMPDEST 0000038c: POP 0000038d: PUSH1 0xc9 0000038f: SLOAD 00000390: PUSH2 0x039f 00000393: SWAP1 00000394: PUSH1 0x01 00000396: PUSH1 0x01 00000398: PUSH1 0xa0 0000039a: SHL 0000039b: SUB 0000039c: AND 0000039d: DUP2 0000039e: JUMP 0000039f: JUMPDEST 000003a0: PUSH1 0x40 000003a2: MLOAD 000003a3: PUSH1 0x01 000003a5: PUSH1 0x01 000003a7: PUSH1 0xa0 000003a9: SHL 000003aa: SUB 000003ab: SWAP1 000003ac: SWAP2 000003ad: AND 000003ae: DUP2 000003af: MSTORE 000003b0: PUSH1 0x20 000003b2: ADD 000003b3: PUSH2 0x0240 000003b6: JUMP 000003b7: JUMPDEST 000003b8: CALLVALUE 000003b9: DUP1 000003ba: ISZERO 000003bb: PUSH2 0x03c3 000003be: JUMPI 000003bf: PUSH1 0x00 000003c1: DUP1 000003c2: REVERT 000003c3: JUMPDEST 000003c4: POP 000003c5: PUSH2 0x0234 000003c8: PUSH2 0x03d2 000003cb: CALLDATASIZE 000003cc: PUSH1 0x04 000003ce: PUSH2 0x25b7 000003d1: JUMP 000003d2: JUMPDEST 000003d3: PUSH2 0x0ca2 000003d6: JUMP 000003d7: JUMPDEST 000003d8: CALLVALUE 000003d9: DUP1 000003da: ISZERO 000003db: PUSH2 0x03e3 000003de: JUMPI 000003df: PUSH1 0x00 000003e1: DUP1 000003e2: REVERT 000003e3: JUMPDEST 000003e4: POP 000003e5: PUSH2 0x02cd 000003e8: PUSH2 0x03f2 000003eb: CALLDATASIZE 000003ec: PUSH1 0x04 000003ee: PUSH2 0x25e3 000003f1: JUMP 000003f2: JUMPDEST 000003f3: PUSH2 0x0db1 000003f6: JUMP 000003f7: JUMPDEST 000003f8: CALLVALUE 000003f9: DUP1 000003fa: ISZERO 000003fb: PUSH2 0x0403 000003fe: JUMPI 000003ff: PUSH1 0x00 00000401: DUP1 00000402: REVERT 00000403: JUMPDEST 00000404: POP 00000405: PUSH2 0x025f 00000408: PUSH2 0x0412 0000040b: CALLDATASIZE 0000040c: PUSH1 0x04 0000040e: PUSH2 0x2611 00000411: JUMP 00000412: JUMPDEST 00000413: PUSH2 0x0e98 00000416: JUMP 00000417: JUMPDEST 00000418: CALLVALUE 00000419: DUP1 0000041a: ISZERO 0000041b: PUSH2 0x0423 0000041e: JUMPI 0000041f: PUSH1 0x00 00000421: DUP1 00000422: REVERT 00000423: JUMPDEST 00000424: POP 00000425: PUSH1 0xca 00000427: SLOAD 00000428: PUSH2 0x039f 0000042b: SWAP1 0000042c: PUSH1 0x01 0000042e: PUSH1 0x01 00000430: PUSH1 0xa0 00000432: SHL 00000433: SUB 00000434: AND 00000435: DUP2 00000436: JUMP 00000437: JUMPDEST 00000438: CALLVALUE 00000439: DUP1 0000043a: ISZERO 0000043b: PUSH2 0x0443 0000043e: JUMPI 0000043f: PUSH1 0x00 00000441: DUP1 00000442: REVERT 00000443: JUMPDEST 00000444: POP 00000445: PUSH2 0x02cd 00000448: PUSH2 0x0452 0000044b: CALLDATASIZE 0000044c: PUSH1 0x04 0000044e: PUSH2 0x2659 00000451: JUMP 00000452: JUMPDEST 00000453: PUSH2 0x111a 00000456: JUMP 00000457: JUMPDEST 00000458: CALLVALUE 00000459: DUP1 0000045a: ISZERO 0000045b: PUSH2 0x0463 0000045e: JUMPI 0000045f: PUSH1 0x00 00000461: DUP1 00000462: REVERT 00000463: JUMPDEST 00000464: POP 00000465: PUSH2 0x02cd 00000468: PUSH2 0x0472 0000046b: CALLDATASIZE 0000046c: PUSH1 0x04 0000046e: PUSH2 0x257c 00000471: JUMP 00000472: JUMPDEST 00000473: PUSH2 0x1246 00000476: JUMP 00000477: JUMPDEST 00000478: CALLVALUE 00000479: DUP1 0000047a: ISZERO 0000047b: PUSH2 0x0483 0000047e: JUMPI 0000047f: PUSH1 0x00 00000481: DUP1 00000482: REVERT 00000483: JUMPDEST 00000484: POP 00000485: PUSH2 0x025f 00000488: PUSH2 0x0492 0000048b: CALLDATASIZE 0000048c: PUSH1 0x04 0000048e: PUSH2 0x254c 00000491: JUMP 00000492: JUMPDEST 00000493: PUSH2 0x12fd 00000496: JUMP 00000497: JUMPDEST 00000498: CALLVALUE 00000499: DUP1 0000049a: ISZERO 0000049b: PUSH2 0x04a3 0000049e: JUMPI 0000049f: PUSH1 0x00 000004a1: DUP1 000004a2: REVERT 000004a3: JUMPDEST 000004a4: POP 000004a5: PUSH2 0x039f 000004a8: PUSH2 0x04b2 000004ab: CALLDATASIZE 000004ac: PUSH1 0x04 000004ae: PUSH2 0x257c 000004b1: JUMP 000004b2: JUMPDEST 000004b3: PUSH1 0xcb 000004b5: PUSH1 0x20 000004b7: MSTORE 000004b8: PUSH1 0x00 000004ba: SWAP1 000004bb: DUP2 000004bc: MSTORE 000004bd: PUSH1 0x40 000004bf: SWAP1 000004c0: KECCAK256 000004c1: SLOAD 000004c2: PUSH1 0x01 000004c4: PUSH1 0x01 000004c6: PUSH1 0xa0 000004c8: SHL 000004c9: SUB 000004ca: AND 000004cb: DUP2 000004cc: JUMP 000004cd: JUMPDEST 000004ce: CALLVALUE 000004cf: DUP1 000004d0: ISZERO 000004d1: PUSH2 0x04d9 000004d4: JUMPI 000004d5: PUSH1 0x00 000004d7: DUP1 000004d8: REVERT 000004d9: JUMPDEST 000004da: POP 000004db: PUSH2 0x039f 000004de: PUSH2 0x04e8 000004e1: CALLDATASIZE 000004e2: PUSH1 0x04 000004e4: PUSH2 0x257c 000004e7: JUMP 000004e8: JUMPDEST 000004e9: PUSH2 0x13b5 000004ec: JUMP 000004ed: JUMPDEST 000004ee: CALLVALUE 000004ef: DUP1 000004f0: ISZERO 000004f1: PUSH2 0x04f9 000004f4: JUMPI 000004f5: PUSH1 0x00 000004f7: DUP1 000004f8: REVERT 000004f9: JUMPDEST 000004fa: POP 000004fb: PUSH2 0x0234 000004fe: PUSH2 0x0508 00000501: CALLDATASIZE 00000502: PUSH1 0x04 00000504: PUSH2 0x25b7 00000507: JUMP 00000508: JUMPDEST 00000509: PUSH1 0xcd 0000050b: PUSH1 0x20 0000050d: SWAP1 0000050e: DUP2 0000050f: MSTORE 00000510: PUSH1 0x00 00000512: SWAP3 00000513: DUP4 00000514: MSTORE 00000515: PUSH1 0x40 00000517: DUP1 00000518: DUP5 00000519: KECCAK256 0000051a: SWAP1 0000051b: SWAP2 0000051c: MSTORE 0000051d: SWAP1 0000051e: DUP3 0000051f: MSTORE 00000520: SWAP1 00000521: KECCAK256 00000522: SLOAD 00000523: PUSH1 0xff 00000525: AND 00000526: DUP2 00000527: JUMP 00000528: JUMPDEST 00000529: CALLVALUE 0000052a: DUP1 0000052b: ISZERO 0000052c: PUSH2 0x0534 0000052f: JUMPI 00000530: PUSH1 0x00 00000532: DUP1 00000533: REVERT 00000534: JUMPDEST 00000535: POP 00000536: PUSH2 0x039f 00000539: PUSH2 0x0543 0000053c: CALLDATASIZE 0000053d: PUSH1 0x04 0000053f: PUSH2 0x2595 00000542: JUMP 00000543: JUMPDEST 00000544: PUSH2 0x1441 00000547: JUMP 00000548: JUMPDEST 00000549: CALLVALUE 0000054a: DUP1 0000054b: ISZERO 0000054c: PUSH2 0x0554 0000054f: JUMPI 00000550: PUSH1 0x00 00000552: DUP1 00000553: REVERT 00000554: JUMPDEST 00000555: POP 00000556: PUSH2 0x0234 00000559: PUSH2 0x0563 0000055c: CALLDATASIZE 0000055d: PUSH1 0x04 0000055f: PUSH2 0x254c 00000562: JUMP 00000563: JUMPDEST 00000564: PUSH2 0x1459 00000567: JUMP 00000568: JUMPDEST 00000569: CALLVALUE 0000056a: DUP1 0000056b: ISZERO 0000056c: PUSH2 0x0574 0000056f: JUMPI 00000570: PUSH1 0x00 00000572: DUP1 00000573: REVERT 00000574: JUMPDEST 00000575: POP 00000576: PUSH2 0x02cd 00000579: PUSH2 0x0583 0000057c: CALLDATASIZE 0000057d: PUSH1 0x04 0000057f: PUSH2 0x269b 00000582: JUMP 00000583: JUMPDEST 00000584: PUSH2 0x1484 00000587: JUMP 00000588: JUMPDEST 00000589: CALLVALUE 0000058a: DUP1 0000058b: ISZERO 0000058c: PUSH2 0x0594 0000058f: JUMPI 00000590: PUSH1 0x00 00000592: DUP1 00000593: REVERT 00000594: JUMPDEST 00000595: POP 00000596: PUSH2 0x025f 00000599: PUSH1 0xce 0000059b: SLOAD 0000059c: DUP2 0000059d: JUMP 0000059e: JUMPDEST 0000059f: CALLVALUE 000005a0: DUP1 000005a1: ISZERO 000005a2: PUSH2 0x05aa 000005a5: JUMPI 000005a6: PUSH1 0x00 000005a8: DUP1 000005a9: REVERT 000005aa: JUMPDEST 000005ab: POP 000005ac: PUSH2 0x025f 000005af: PUSH1 0x00 000005b1: DUP2 000005b2: JUMP 000005b3: JUMPDEST 000005b4: CALLVALUE 000005b5: DUP1 000005b6: ISZERO 000005b7: PUSH2 0x05bf 000005ba: JUMPI 000005bb: PUSH1 0x00 000005bd: DUP1 000005be: REVERT 000005bf: JUMPDEST 000005c0: POP 000005c1: PUSH2 0x0234 000005c4: PUSH2 0x05ce 000005c7: CALLDATASIZE 000005c8: PUSH1 0x04 000005ca: PUSH2 0x254c 000005cd: JUMP 000005ce: JUMPDEST 000005cf: PUSH2 0x1707 000005d2: JUMP 000005d3: JUMPDEST 000005d4: CALLVALUE 000005d5: DUP1 000005d6: ISZERO 000005d7: PUSH2 0x05df 000005da: JUMPI 000005db: PUSH1 0x00 000005dd: DUP1 000005de: REVERT 000005df: JUMPDEST 000005e0: POP 000005e1: PUSH2 0x0234 000005e4: PUSH2 0x05ee 000005e7: CALLDATASIZE 000005e8: PUSH1 0x04 000005ea: PUSH2 0x2659 000005ed: JUMP 000005ee: JUMPDEST 000005ef: PUSH2 0x17d1 000005f2: JUMP 000005f3: JUMPDEST 000005f4: CALLVALUE 000005f5: DUP1 000005f6: ISZERO 000005f7: PUSH2 0x05ff 000005fa: JUMPI 000005fb: PUSH1 0x00 000005fd: DUP1 000005fe: REVERT 000005ff: JUMPDEST 00000600: POP 00000601: PUSH2 0x025f 00000604: PUSH32 0x96e3fc3be15159903e053027cff8a23f39a990e0194abcd8ac1cf1b355b8b93c 00000625: DUP2 00000626: JUMP 00000627: JUMPDEST 00000628: CALLVALUE 00000629: DUP1 0000062a: ISZERO 0000062b: PUSH2 0x0633 0000062e: JUMPI 0000062f: PUSH1 0x00 00000631: DUP1 00000632: REVERT 00000633: JUMPDEST 00000634: POP 00000635: PUSH2 0x02cd 00000638: PUSH2 0x0642 0000063b: CALLDATASIZE 0000063c: PUSH1 0x04 0000063e: PUSH2 0x26e7 00000641: JUMP 00000642: JUMPDEST 00000643: PUSH2 0x1843 00000646: JUMP 00000647: JUMPDEST 00000648: CALLVALUE 00000649: DUP1 0000064a: ISZERO 0000064b: PUSH2 0x0653 0000064e: JUMPI 0000064f: PUSH1 0x00 00000651: DUP1 00000652: REVERT 00000653: JUMPDEST 00000654: POP 00000655: PUSH2 0x02cd 00000658: PUSH2 0x0662 0000065b: CALLDATASIZE 0000065c: PUSH1 0x04 0000065e: PUSH2 0x2727 00000661: JUMP 00000662: JUMPDEST 00000663: PUSH2 0x193a 00000666: JUMP 00000667: JUMPDEST 00000668: CALLVALUE 00000669: DUP1 0000066a: ISZERO 0000066b: PUSH2 0x0673 0000066e: JUMPI 0000066f: PUSH1 0x00 00000671: DUP1 00000672: REVERT 00000673: JUMPDEST 00000674: POP 00000675: PUSH2 0x025f 00000678: PUSH1 0x00 0000067a: DUP1 0000067b: MLOAD 0000067c: PUSH1 0x20 0000067e: PUSH2 0x2a15 00000681: DUP4 00000682: CODECOPY 00000683: DUP2 00000684: MLOAD 00000685: SWAP2 00000686: MSTORE 00000687: DUP2 00000688: JUMP 00000689: JUMPDEST 0000068a: CALLVALUE 0000068b: DUP1 0000068c: ISZERO 0000068d: PUSH2 0x0695 00000690: JUMPI 00000691: PUSH1 0x00 00000693: DUP1 00000694: REVERT 00000695: JUMPDEST 00000696: POP 00000697: PUSH2 0x025f 0000069a: PUSH2 0x06a4 0000069d: CALLDATASIZE 0000069e: PUSH1 0x04 000006a0: PUSH2 0x257c 000006a3: JUMP 000006a4: JUMPDEST 000006a5: PUSH2 0x1a2a 000006a8: JUMP 000006a9: JUMPDEST 000006aa: CALLVALUE 000006ab: DUP1 000006ac: ISZERO 000006ad: PUSH2 0x06b5 000006b0: JUMPI 000006b1: PUSH1 0x00 000006b3: DUP1 000006b4: REVERT 000006b5: JUMPDEST 000006b6: POP 000006b7: PUSH2 0x02cd 000006ba: PUSH2 0x06c4 000006bd: CALLDATASIZE 000006be: PUSH1 0x04 000006c0: PUSH2 0x254c 000006c3: JUMP 000006c4: JUMPDEST 000006c5: PUSH2 0x1a41 000006c8: JUMP 000006c9: JUMPDEST 000006ca: CALLVALUE 000006cb: DUP1 000006cc: ISZERO 000006cd: PUSH2 0x06d5 000006d0: JUMPI 000006d1: PUSH1 0x00 000006d3: DUP1 000006d4: REVERT 000006d5: JUMPDEST 000006d6: POP 000006d7: PUSH2 0x025f 000006da: PUSH1 0xcf 000006dc: SLOAD 000006dd: DUP2 000006de: JUMP 000006df: JUMPDEST 000006e0: PUSH2 0x02cd 000006e3: PUSH2 0x06ed 000006e6: CALLDATASIZE 000006e7: PUSH1 0x04 000006e9: PUSH2 0x24f5 000006ec: JUMP 000006ed: JUMPDEST 000006ee: PUSH2 0x1a66 000006f1: JUMP 000006f2: JUMPDEST 000006f3: PUSH1 0x00 000006f5: PUSH1 0x01 000006f7: PUSH1 0x01 000006f9: PUSH1 0xe0 000006fb: SHL 000006fc: SUB 000006fd: NOT 000006fe: DUP3 000006ff: AND 00000700: PUSH4 0x5a05180f 00000705: PUSH1 0xe0 00000707: SHL 00000708: EQ 00000709: DUP1 0000070a: PUSH2 0x0717 0000070d: JUMPI 0000070e: POP 0000070f: PUSH2 0x0717 00000712: DUP3 00000713: PUSH2 0x1c10 00000716: JUMP 00000717: JUMPDEST 00000718: SWAP3 00000719: SWAP2 0000071a: POP 0000071b: POP 0000071c: JUMP 0000071d: JUMPDEST 0000071e: PUSH1 0xca 00000720: SLOAD 00000721: PUSH1 0x00 00000723: SWAP1 00000724: PUSH1 0x01 00000726: PUSH1 0x01 00000728: PUSH1 0xa0 0000072a: SHL 0000072b: SUB 0000072c: AND 0000072d: CALLER 0000072e: EQ 0000072f: PUSH2 0x077f 00000732: JUMPI 00000733: PUSH1 0x40 00000735: MLOAD 00000736: PUSH3 0x461bcd 0000073a: PUSH1 0xe5 0000073c: SHL 0000073d: DUP2 0000073e: MSTORE 0000073f: PUSH1 0x20 00000741: PUSH1 0x04 00000743: DUP3 00000744: ADD 00000745: MSTORE 00000746: PUSH1 0x1c 00000748: PUSH1 0x24 0000074a: DUP3 0000074b: ADD 0000074c: MSTORE 0000074d: PUSH32 0x53656e646572206973206e6f742061204d65737361676550726f787900000000 0000076e: PUSH1 0x44 00000770: DUP3 00000771: ADD 00000772: MSTORE 00000773: PUSH1 0x64 00000775: ADD 00000776: JUMPDEST 00000777: PUSH1 0x40 00000779: MLOAD 0000077a: DUP1 0000077b: SWAP2 0000077c: SUB 0000077d: SWAP1 0000077e: REVERT 0000077f: JUMPDEST 00000780: DUP2 00000781: ISZERO 00000782: PUSH2 0x087c 00000785: JUMPI 00000786: PUSH1 0xc9 00000788: SLOAD 00000789: PUSH1 0x40 0000078b: MLOAD 0000078c: PUSH4 0x35817773 00000791: PUSH1 0xe0 00000793: SHL 00000794: DUP2 00000795: MSTORE 00000796: PUSH1 0x20 00000798: PUSH1 0x04 0000079a: DUP3 0000079b: ADD 0000079c: MSTORE 0000079d: PUSH1 0x07 0000079f: PUSH1 0x24 000007a1: DUP3 000007a2: ADD 000007a3: MSTORE 000007a4: PUSH7 0x57616c6c657473 000007ac: PUSH1 0xc8 000007ae: SHL 000007af: PUSH1 0x44 000007b1: DUP3 000007b2: ADD 000007b3: MSTORE 000007b4: PUSH1 0x01 000007b6: PUSH1 0x01 000007b8: PUSH1 0xa0 000007ba: SHL 000007bb: SUB 000007bc: SWAP1 000007bd: SWAP2 000007be: AND 000007bf: SWAP1 000007c0: PUSH4 0x35817773 000007c5: SWAP1 000007c6: PUSH1 0x64 000007c8: ADD 000007c9: PUSH1 0x20 000007cb: PUSH1 0x40 000007cd: MLOAD 000007ce: DUP1 000007cf: DUP4 000007d0: SUB 000007d1: DUP2 000007d2: DUP7 000007d3: GAS 000007d4: STATICCALL 000007d5: ISZERO 000007d6: DUP1 000007d7: ISZERO 000007d8: PUSH2 0x07e5 000007db: JUMPI 000007dc: RETURNDATASIZE 000007dd: PUSH1 0x00 000007df: DUP1 000007e0: RETURNDATACOPY 000007e1: RETURNDATASIZE 000007e2: PUSH1 0x00 000007e4: REVERT 000007e5: JUMPDEST 000007e6: POP 000007e7: POP 000007e8: POP 000007e9: POP 000007ea: PUSH1 0x40 000007ec: MLOAD 000007ed: RETURNDATASIZE 000007ee: PUSH1 0x1f 000007f0: NOT 000007f1: PUSH1 0x1f 000007f3: DUP3 000007f4: ADD 000007f5: AND 000007f6: DUP3 000007f7: ADD 000007f8: DUP1 000007f9: PUSH1 0x40 000007fb: MSTORE 000007fc: POP 000007fd: DUP2 000007fe: ADD 000007ff: SWAP1 00000800: PUSH2 0x0809 00000803: SWAP2 00000804: SWAP1 00000805: PUSH2 0x2744 00000808: JUMP 00000809: JUMPDEST 0000080a: PUSH1 0x40 0000080c: MLOAD 0000080d: PUSH4 0x37e9add9 00000812: PUSH1 0xe0 00000814: SHL 00000815: DUP2 00000816: MSTORE 00000817: PUSH1 0x04 00000819: DUP2 0000081a: ADD 0000081b: DUP7 0000081c: SWAP1 0000081d: MSTORE 0000081e: PUSH1 0x01 00000820: PUSH1 0x01 00000822: PUSH1 0xa0 00000824: SHL 00000825: SUB 00000826: DUP6 00000827: DUP2 00000828: AND 00000829: PUSH1 0x24 0000082b: DUP4 0000082c: ADD 0000082d: MSTORE 0000082e: PUSH1 0x44 00000830: DUP3 00000831: ADD 00000832: DUP6 00000833: SWAP1 00000834: MSTORE 00000835: PUSH1 0x00 00000837: PUSH1 0x64 00000839: DUP4 0000083a: ADD 0000083b: MSTORE 0000083c: SWAP2 0000083d: SWAP1 0000083e: SWAP2 0000083f: AND 00000840: SWAP1 00000841: PUSH4 0x37e9add9 00000846: SWAP1 00000847: PUSH1 0x84 00000849: ADD 0000084a: PUSH1 0x00 0000084c: PUSH1 0x40 0000084e: MLOAD 0000084f: DUP1 00000850: DUP4 00000851: SUB 00000852: DUP2 00000853: PUSH1 0x00 00000855: DUP8 00000856: DUP1 00000857: EXTCODESIZE 00000858: ISZERO 00000859: DUP1 0000085a: ISZERO 0000085b: PUSH2 0x0863 0000085e: JUMPI 0000085f: PUSH1 0x00 00000861: DUP1 00000862: REVERT 00000863: JUMPDEST 00000864: POP 00000865: GAS 00000866: CALL 00000867: ISZERO 00000868: DUP1 00000869: ISZERO 0000086a: PUSH2 0x0877 0000086d: JUMPI 0000086e: RETURNDATASIZE 0000086f: PUSH1 0x00 00000871: DUP1 00000872: RETURNDATACOPY 00000873: RETURNDATASIZE 00000874: PUSH1 0x00 00000876: REVERT 00000877: JUMPDEST 00000878: POP 00000879: POP 0000087a: POP 0000087b: POP 0000087c: JUMPDEST 0000087d: POP 0000087e: PUSH1 0x01 00000880: SWAP4 00000881: SWAP3 00000882: POP 00000883: POP 00000884: POP 00000885: JUMP 00000886: JUMPDEST 00000887: PUSH1 0x01 00000889: PUSH1 0x01 0000088b: PUSH1 0xa0 0000088d: SHL 0000088e: SUB 0000088f: DUP4 00000890: AND 00000891: PUSH1 0x00 00000893: SWAP1 00000894: DUP2 00000895: MSTORE 00000896: PUSH1 0xcc 00000898: PUSH1 0x20 0000089a: SWAP1 0000089b: DUP2 0000089c: MSTORE 0000089d: PUSH1 0x40 0000089f: DUP1 000008a0: DUP4 000008a1: KECCAK256 000008a2: DUP2 000008a3: MLOAD 000008a4: PUSH1 0x1f 000008a6: DUP7 000008a7: ADD 000008a8: DUP5 000008a9: SWAP1 000008aa: DIV 000008ab: DUP5 000008ac: MUL 000008ad: DUP2 000008ae: ADD 000008af: DUP5 000008b0: ADD 000008b1: SWAP1 000008b2: SWAP3 000008b3: MSTORE 000008b4: DUP5 000008b5: DUP3 000008b6: MSTORE 000008b7: SWAP2 000008b8: DUP4 000008b9: SWAP2 000008ba: PUSH2 0x08dd 000008bd: SWAP2 000008be: DUP8 000008bf: SWAP1 000008c0: DUP8 000008c1: SWAP1 000008c2: DUP2 000008c3: SWAP1 000008c4: DUP5 000008c5: ADD 000008c6: DUP4 000008c7: DUP3 000008c8: DUP1 000008c9: DUP3 000008ca: DUP5 000008cb: CALLDATACOPY 000008cc: PUSH1 0x00 000008ce: SWAP3 000008cf: ADD 000008d0: SWAP2 000008d1: SWAP1 000008d2: SWAP2 000008d3: MSTORE 000008d4: POP 000008d5: PUSH2 0x1c45 000008d8: SWAP3 000008d9: POP 000008da: POP 000008db: POP 000008dc: JUMP 000008dd: JUMPDEST 000008de: DUP2 000008df: MSTORE 000008e0: PUSH1 0x20 000008e2: ADD 000008e3: SWAP1 000008e4: DUP2 000008e5: MSTORE 000008e6: PUSH1 0x20 000008e8: ADD 000008e9: PUSH1 0x00 000008eb: KECCAK256 000008ec: SLOAD 000008ed: SWAP1 000008ee: POP 000008ef: SWAP4 000008f0: SWAP3 000008f1: POP 000008f2: POP 000008f3: POP 000008f4: JUMP 000008f5: JUMPDEST 000008f6: PUSH1 0x00 000008f8: PUSH2 0x0936 000008fb: DUP5 000008fc: DUP5 000008fd: DUP1 000008fe: DUP1 000008ff: PUSH1 0x1f 00000901: ADD 00000902: PUSH1 0x20 00000904: DUP1 00000905: SWAP2 00000906: DIV 00000907: MUL 00000908: PUSH1 0x20 0000090a: ADD 0000090b: PUSH1 0x40 0000090d: MLOAD 0000090e: SWAP1 0000090f: DUP2 00000910: ADD 00000911: PUSH1 0x40 00000913: MSTORE 00000914: DUP1 00000915: SWAP4 00000916: SWAP3 00000917: SWAP2 00000918: SWAP1 00000919: DUP2 0000091a: DUP2 0000091b: MSTORE 0000091c: PUSH1 0x20 0000091e: ADD 0000091f: DUP4 00000920: DUP4 00000921: DUP1 00000922: DUP3 00000923: DUP5 00000924: CALLDATACOPY 00000925: PUSH1 0x00 00000927: SWAP3 00000928: ADD 00000929: SWAP2 0000092a: SWAP1 0000092b: SWAP2 0000092c: MSTORE 0000092d: POP 0000092e: PUSH2 0x1c45 00000931: SWAP3 00000932: POP 00000933: POP 00000934: POP 00000935: JUMP 00000936: JUMPDEST 00000937: SWAP1 00000938: POP 00000939: PUSH2 0x0950 0000093c: PUSH1 0x00 0000093e: DUP1 0000093f: MLOAD 00000940: PUSH1 0x20 00000942: PUSH2 0x2a15 00000945: DUP4 00000946: CODECOPY 00000947: DUP2 00000948: MLOAD 00000949: SWAP2 0000094a: MSTORE 0000094b: CALLER 0000094c: PUSH2 0x1459 0000094f: JUMP 00000950: JUMPDEST 00000951: DUP1 00000952: PUSH2 0x0960 00000955: JUMPI 00000956: POP 00000957: PUSH2 0x0960 0000095a: CALLER 0000095b: DUP3 0000095c: PUSH2 0x0ca2 0000095f: JUMP 00000960: JUMPDEST 00000961: PUSH2 0x09a4 00000964: JUMPI 00000965: PUSH1 0x40 00000967: MLOAD 00000968: PUSH3 0x461bcd 0000096c: PUSH1 0xe5 0000096e: SHL 0000096f: DUP2 00000970: MSTORE 00000971: PUSH1 0x20 00000973: PUSH1 0x04 00000975: DUP3 00000976: ADD 00000977: MSTORE 00000978: PUSH1 0x15 0000097a: PUSH1 0x24 0000097c: DUP3 0000097d: ADD 0000097e: MSTORE 0000097f: PUSH21 0x2737ba1030baba3437b934bd32b21031b0b63632b9 00000995: PUSH1 0x59 00000997: SHL 00000998: PUSH1 0x44 0000099a: DUP3 0000099b: ADD 0000099c: MSTORE 0000099d: PUSH1 0x64 0000099f: ADD 000009a0: PUSH2 0x0776 000009a3: JUMP 000009a4: JUMPDEST 000009a5: PUSH1 0x00 000009a7: DUP2 000009a8: DUP2 000009a9: MSTORE 000009aa: PUSH1 0xcb 000009ac: PUSH1 0x20 000009ae: MSTORE 000009af: PUSH1 0x40 000009b1: SWAP1 000009b2: KECCAK256 000009b3: SLOAD 000009b4: PUSH1 0x01 000009b6: PUSH1 0x01 000009b8: PUSH1 0xa0 000009ba: SHL 000009bb: SUB 000009bc: AND 000009bd: ISZERO 000009be: PUSH2 0x0a09 000009c1: JUMPI 000009c2: PUSH1 0x40 000009c4: MLOAD 000009c5: PUSH3 0x461bcd 000009c9: PUSH1 0xe5 000009cb: SHL 000009cc: DUP2 000009cd: MSTORE 000009ce: PUSH1 0x20 000009d0: PUSH1 0x04 000009d2: DUP3 000009d3: ADD 000009d4: MSTORE 000009d5: PUSH1 0x1a 000009d7: PUSH1 0x24 000009d9: DUP3 000009da: ADD 000009db: MSTORE 000009dc: PUSH32 0x534b414c4520636861696e20697320616c726561647920736574000000000000 000009fd: PUSH1 0x44 000009ff: DUP3 00000a00: ADD 00000a01: MSTORE 00000a02: PUSH1 0x64 00000a04: ADD 00000a05: PUSH2 0x0776 00000a08: JUMP 00000a09: JUMPDEST 00000a0a: PUSH1 0x01 00000a0c: PUSH1 0x01 00000a0e: PUSH1 0xa0 00000a10: SHL 00000a11: SUB 00000a12: DUP3 00000a13: AND 00000a14: PUSH2 0x0a78 00000a17: JUMPI 00000a18: PUSH1 0x40 00000a1a: MLOAD 00000a1b: PUSH3 0x461bcd 00000a1f: PUSH1 0xe5 00000a21: SHL 00000a22: DUP2 00000a23: MSTORE 00000a24: PUSH1 0x20 00000a26: PUSH1 0x04 00000a28: DUP3 00000a29: ADD 00000a2a: MSTORE 00000a2b: PUSH1 0x30 00000a2d: PUSH1 0x24 00000a2f: DUP3 00000a30: ADD 00000a31: MSTORE 00000a32: PUSH32 0x496e636f72726563742061646472657373206f6620636f6e7472616374207265 00000a53: PUSH1 0x44 00000a55: DUP3 00000a56: ADD 00000a57: MSTORE 00000a58: PUSH16 0x31b2b4bb32b91037b71029b1b430b4b7 00000a69: PUSH1 0x81 00000a6b: SHL 00000a6c: PUSH1 0x64 00000a6e: DUP3 00000a6f: ADD 00000a70: MSTORE 00000a71: PUSH1 0x84 00000a73: ADD 00000a74: PUSH2 0x0776 00000a77: JUMP 00000a78: JUMPDEST 00000a79: PUSH1 0x00 00000a7b: SWAP1 00000a7c: DUP2 00000a7d: MSTORE 00000a7e: PUSH1 0xcb 00000a80: PUSH1 0x20 00000a82: MSTORE 00000a83: PUSH1 0x40 00000a85: SWAP1 00000a86: KECCAK256 00000a87: DUP1 00000a88: SLOAD 00000a89: PUSH1 0x01 00000a8b: PUSH1 0x01 00000a8d: PUSH1 0xa0 00000a8f: SHL 00000a90: SUB 00000a91: NOT 00000a92: AND 00000a93: PUSH1 0x01 00000a95: PUSH1 0x01 00000a97: PUSH1 0xa0 00000a99: SHL 00000a9a: SUB 00000a9b: SWAP3 00000a9c: SWAP1 00000a9d: SWAP3 00000a9e: AND 00000a9f: SWAP2 00000aa0: SWAP1 00000aa1: SWAP2 00000aa2: OR 00000aa3: SWAP1 00000aa4: SSTORE 00000aa5: POP 00000aa6: POP 00000aa7: JUMP 00000aa8: JUMPDEST 00000aa9: PUSH1 0x01 00000aab: PUSH1 0x01 00000aad: PUSH1 0xa0 00000aaf: SHL 00000ab0: SUB 00000ab1: DUP2 00000ab2: AND 00000ab3: PUSH1 0x00 00000ab5: SWAP1 00000ab6: DUP2 00000ab7: MSTORE 00000ab8: PUSH1 0xcd 00000aba: PUSH1 0x20 00000abc: SWAP1 00000abd: DUP2 00000abe: MSTORE 00000abf: PUSH1 0x40 00000ac1: DUP1 00000ac2: DUP4 00000ac3: KECCAK256 00000ac4: DUP6 00000ac5: DUP5 00000ac6: MSTORE 00000ac7: SWAP1 00000ac8: SWAP2 00000ac9: MSTORE 00000aca: DUP2 00000acb: KECCAK256 00000acc: SLOAD 00000acd: PUSH1 0xff 00000acf: AND 00000ad0: DUP1 00000ad1: ISZERO 00000ad2: PUSH2 0x0ae2 00000ad5: JUMPI 00000ad6: POP 00000ad7: PUSH2 0x0ae2 00000ada: DUP4 00000adb: DUP4 00000adc: PUSH1 0x00 00000ade: PUSH2 0x1c75 00000ae1: JUMP 00000ae2: JUMPDEST 00000ae3: SWAP4 00000ae4: SWAP3 00000ae5: POP 00000ae6: POP 00000ae7: POP 00000ae8: JUMP 00000ae9: JUMPDEST 00000aea: PUSH1 0x00 00000aec: DUP3 00000aed: DUP2 00000aee: MSTORE 00000aef: PUSH1 0x65 00000af1: PUSH1 0x20 00000af3: MSTORE 00000af4: PUSH1 0x40 00000af6: SWAP1 00000af7: KECCAK256 00000af8: PUSH1 0x01 00000afa: ADD 00000afb: SLOAD 00000afc: PUSH2 0x0b04 00000aff: DUP2 00000b00: PUSH2 0x1cbd 00000b03: JUMP 00000b04: JUMPDEST 00000b05: PUSH2 0x0b0e 00000b08: DUP4 00000b09: DUP4 00000b0a: PUSH2 0x1cca 00000b0d: JUMP 00000b0e: JUMPDEST 00000b0f: POP 00000b10: POP 00000b11: POP 00000b12: JUMP 00000b13: JUMPDEST 00000b14: PUSH2 0x0b3d 00000b17: PUSH32 0x96e3fc3be15159903e053027cff8a23f39a990e0194abcd8ac1cf1b355b8b93c 00000b38: CALLER 00000b39: PUSH2 0x1459 00000b3c: JUMP 00000b3d: JUMPDEST 00000b3e: PUSH2 0x0b89 00000b41: JUMPI 00000b42: PUSH1 0x40 00000b44: MLOAD 00000b45: PUSH3 0x461bcd 00000b49: PUSH1 0xe5 00000b4b: SHL 00000b4c: DUP2 00000b4d: MSTORE 00000b4e: PUSH1 0x20 00000b50: PUSH1 0x04 00000b52: DUP3 00000b53: ADD 00000b54: DUP2 00000b55: SWAP1 00000b56: MSTORE 00000b57: PUSH1 0x24 00000b59: DUP3 00000b5a: ADD 00000b5b: MSTORE 00000b5c: PUSH32 0x434f4e5354414e545f5345545445525f524f4c45206973207265717569726564 00000b7d: PUSH1 0x44 00000b7f: DUP3 00000b80: ADD 00000b81: MSTORE 00000b82: PUSH1 0x64 00000b84: ADD 00000b85: PUSH2 0x0776 00000b88: JUMP 00000b89: JUMPDEST 00000b8a: PUSH1 0x00 00000b8c: DUP2 00000b8d: GT 00000b8e: PUSH2 0x0bcb 00000b91: JUMPI 00000b92: PUSH1 0x40 00000b94: MLOAD 00000b95: PUSH3 0x461bcd 00000b99: PUSH1 0xe5 00000b9b: SHL 00000b9c: DUP2 00000b9d: MSTORE 00000b9e: PUSH1 0x20 00000ba0: PUSH1 0x04 00000ba2: DUP3 00000ba3: ADD 00000ba4: MSTORE 00000ba5: PUSH1 0x0f 00000ba7: PUSH1 0x24 00000ba9: DUP3 00000baa: ADD 00000bab: MSTORE 00000bac: PUSH15 0x44697669646572206973207a65726f 00000bbc: PUSH1 0x88 00000bbe: SHL 00000bbf: PUSH1 0x44 00000bc1: DUP3 00000bc2: ADD 00000bc3: MSTORE 00000bc4: PUSH1 0x64 00000bc6: ADD 00000bc7: PUSH2 0x0776 00000bca: JUMP 00000bcb: JUMPDEST 00000bcc: PUSH1 0xcf 00000bce: SLOAD 00000bcf: PUSH1 0xd0 00000bd1: SLOAD 00000bd2: PUSH1 0x40 00000bd4: DUP1 00000bd5: MLOAD 00000bd6: SWAP3 00000bd7: DUP4 00000bd8: MSTORE 00000bd9: PUSH1 0x20 00000bdb: DUP4 00000bdc: ADD 00000bdd: SWAP2 00000bde: SWAP1 00000bdf: SWAP2 00000be0: MSTORE 00000be1: DUP2 00000be2: ADD 00000be3: DUP4 00000be4: SWAP1 00000be5: MSTORE 00000be6: PUSH1 0x60 00000be8: DUP2 00000be9: ADD 00000bea: DUP3 00000beb: SWAP1 00000bec: MSTORE 00000bed: PUSH32 0x52a64da4541dabf311206f46c57caaa217b96d6647e455c52e6dd7110abf20ab 00000c0e: SWAP1 00000c0f: PUSH1 0x80 00000c11: ADD 00000c12: PUSH1 0x40 00000c14: MLOAD 00000c15: DUP1 00000c16: SWAP2 00000c17: SUB 00000c18: SWAP1 00000c19: LOG1 00000c1a: PUSH1 0xcf 00000c1c: SWAP2 00000c1d: SWAP1 00000c1e: SWAP2 00000c1f: SSTORE 00000c20: PUSH1 0xd0 00000c22: SSTORE 00000c23: JUMP 00000c24: JUMPDEST 00000c25: PUSH1 0x01 00000c27: PUSH1 0x01 00000c29: PUSH1 0xa0 00000c2b: SHL 00000c2c: SUB 00000c2d: DUP2 00000c2e: AND 00000c2f: CALLER 00000c30: EQ 00000c31: PUSH2 0x0c94 00000c34: JUMPI 00000c35: PUSH1 0x40 00000c37: MLOAD 00000c38: PUSH3 0x461bcd 00000c3c: PUSH1 0xe5 00000c3e: SHL 00000c3f: DUP2 00000c40: MSTORE 00000c41: PUSH1 0x20 00000c43: PUSH1 0x04 00000c45: DUP3 00000c46: ADD 00000c47: MSTORE 00000c48: PUSH1 0x2f 00000c4a: PUSH1 0x24 00000c4c: DUP3 00000c4d: ADD 00000c4e: MSTORE 00000c4f: PUSH32 0x416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e6365 00000c70: PUSH1 0x44 00000c72: DUP3 00000c73: ADD 00000c74: MSTORE 00000c75: PUSH15 0x103937b632b9903337b91039b2b633 00000c85: PUSH1 0x89 00000c87: SHL 00000c88: PUSH1 0x64 00000c8a: DUP3 00000c8b: ADD 00000c8c: MSTORE 00000c8d: PUSH1 0x84 00000c8f: ADD 00000c90: PUSH2 0x0776 00000c93: JUMP 00000c94: JUMPDEST 00000c95: PUSH2 0x0c9e 00000c98: DUP3 00000c99: DUP3 00000c9a: PUSH2 0x1cec 00000c9d: JUMP 00000c9e: JUMPDEST 00000c9f: POP 00000ca0: POP 00000ca1: JUMP 00000ca2: JUMPDEST 00000ca3: PUSH1 0xc9 00000ca5: SLOAD 00000ca6: PUSH1 0x40 00000ca8: MLOAD 00000ca9: PUSH4 0x35817773 00000cae: PUSH1 0xe0 00000cb0: SHL 00000cb1: DUP2 00000cb2: MSTORE 00000cb3: PUSH1 0x20 00000cb5: PUSH1 0x04 00000cb7: DUP3 00000cb8: ADD 00000cb9: MSTORE 00000cba: PUSH1 0x0f 00000cbc: PUSH1 0x24 00000cbe: DUP3 00000cbf: ADD 00000cc0: MSTORE 00000cc1: PUSH15 0x14d8da185a5b9cd25b9d195c9b985b 00000cd1: PUSH1 0x8a 00000cd3: SHL 00000cd4: PUSH1 0x44 00000cd6: DUP3 00000cd7: ADD 00000cd8: MSTORE 00000cd9: PUSH1 0x00 00000cdb: SWAP2 00000cdc: DUP3 00000cdd: SWAP2 00000cde: PUSH1 0x01 00000ce0: PUSH1 0x01 00000ce2: PUSH1 0xa0 00000ce4: SHL 00000ce5: SUB 00000ce6: SWAP1 00000ce7: SWAP2 00000ce8: AND 00000ce9: SWAP1 00000cea: PUSH4 0x35817773 00000cef: SWAP1 00000cf0: PUSH1 0x64 00000cf2: ADD 00000cf3: PUSH1 0x20 00000cf5: PUSH1 0x40 00000cf7: MLOAD 00000cf8: DUP1 00000cf9: DUP4 00000cfa: SUB 00000cfb: DUP2 00000cfc: DUP7 00000cfd: GAS 00000cfe: STATICCALL 00000cff: ISZERO 00000d00: DUP1 00000d01: ISZERO 00000d02: PUSH2 0x0d0f 00000d05: JUMPI 00000d06: RETURNDATASIZE 00000d07: PUSH1 0x00 00000d09: DUP1 00000d0a: RETURNDATACOPY 00000d0b: RETURNDATASIZE 00000d0c: PUSH1 0x00 00000d0e: REVERT 00000d0f: JUMPDEST 00000d10: POP 00000d11: POP 00000d12: POP 00000d13: POP 00000d14: PUSH1 0x40 00000d16: MLOAD 00000d17: RETURNDATASIZE 00000d18: PUSH1 0x1f 00000d1a: NOT 00000d1b: PUSH1 0x1f 00000d1d: DUP3 00000d1e: ADD 00000d1f: AND 00000d20: DUP3 00000d21: ADD 00000d22: DUP1 00000d23: PUSH1 0x40 00000d25: MSTORE 00000d26: POP 00000d27: DUP2 00000d28: ADD 00000d29: SWAP1 00000d2a: PUSH2 0x0d33 00000d2d: SWAP2 00000d2e: SWAP1 00000d2f: PUSH2 0x2744 00000d32: JUMP 00000d33: JUMPDEST 00000d34: PUSH1 0x40 00000d36: MLOAD 00000d37: PUSH4 0x47bf2805 00000d3c: PUSH1 0xe1 00000d3e: SHL 00000d3f: DUP2 00000d40: MSTORE 00000d41: PUSH1 0x01 00000d43: PUSH1 0x01 00000d45: PUSH1 0xa0 00000d47: SHL 00000d48: SUB 00000d49: DUP7 00000d4a: DUP2 00000d4b: AND 00000d4c: PUSH1 0x04 00000d4e: DUP4 00000d4f: ADD 00000d50: MSTORE 00000d51: PUSH1 0x24 00000d53: DUP3 00000d54: ADD 00000d55: DUP7 00000d56: SWAP1 00000d57: MSTORE 00000d58: SWAP2 00000d59: SWAP3 00000d5a: POP 00000d5b: SWAP1 00000d5c: DUP3 00000d5d: AND 00000d5e: SWAP1 00000d5f: PUSH4 0x8f7e500a 00000d64: SWAP1 00000d65: PUSH1 0x44 00000d67: ADD 00000d68: JUMPDEST 00000d69: PUSH1 0x20 00000d6b: PUSH1 0x40 00000d6d: MLOAD 00000d6e: DUP1 00000d6f: DUP4 00000d70: SUB 00000d71: DUP2 00000d72: DUP7 00000d73: GAS 00000d74: STATICCALL 00000d75: ISZERO 00000d76: DUP1 00000d77: ISZERO 00000d78: PUSH2 0x0d85 00000d7b: JUMPI 00000d7c: RETURNDATASIZE 00000d7d: PUSH1 0x00 00000d7f: DUP1 00000d80: RETURNDATACOPY 00000d81: RETURNDATASIZE 00000d82: PUSH1 0x00 00000d84: REVERT 00000d85: JUMPDEST 00000d86: POP 00000d87: POP 00000d88: POP 00000d89: POP 00000d8a: PUSH1 0x40 00000d8c: MLOAD 00000d8d: RETURNDATASIZE 00000d8e: PUSH1 0x1f 00000d90: NOT 00000d91: PUSH1 0x1f 00000d93: DUP3 00000d94: ADD 00000d95: AND 00000d96: DUP3 00000d97: ADD 00000d98: DUP1 00000d99: PUSH1 0x40 00000d9b: MSTORE 00000d9c: POP 00000d9d: DUP2 00000d9e: ADD 00000d9f: SWAP1 00000da0: PUSH2 0x0da9 00000da3: SWAP2 00000da4: SWAP1 00000da5: PUSH2 0x2761 00000da8: JUMP 00000da9: JUMPDEST 00000daa: SWAP5 00000dab: SWAP4 00000dac: POP 00000dad: POP 00000dae: POP 00000daf: POP 00000db0: JUMP 00000db1: JUMPDEST 00000db2: PUSH1 0x00 00000db4: SLOAD 00000db5: PUSH2 0x0100 00000db8: SWAP1 00000db9: DIV 00000dba: PUSH1 0xff 00000dbc: AND 00000dbd: ISZERO 00000dbe: DUP1 00000dbf: DUP1 00000dc0: ISZERO 00000dc1: PUSH2 0x0dd1 00000dc4: JUMPI 00000dc5: POP 00000dc6: PUSH1 0x00 00000dc8: SLOAD 00000dc9: PUSH1 0x01 00000dcb: PUSH1 0xff 00000dcd: SWAP1 00000dce: SWAP2 00000dcf: AND 00000dd0: LT 00000dd1: JUMPDEST 00000dd2: DUP1 00000dd3: PUSH2 0x0deb 00000dd6: JUMPI 00000dd7: POP 00000dd8: ADDRESS 00000dd9: EXTCODESIZE 00000dda: ISZERO 00000ddb: DUP1 00000ddc: ISZERO 00000ddd: PUSH2 0x0deb 00000de0: JUMPI 00000de1: POP 00000de2: PUSH1 0x00 00000de4: SLOAD 00000de5: PUSH1 0xff 00000de7: AND 00000de8: PUSH1 0x01 00000dea: EQ 00000deb: JUMPDEST 00000dec: PUSH2 0x0e07 00000def: JUMPI 00000df0: PUSH1 0x40 00000df2: MLOAD 00000df3: PUSH3 0x461bcd 00000df7: PUSH1 0xe5 00000df9: SHL 00000dfa: DUP2 00000dfb: MSTORE 00000dfc: PUSH1 0x04 00000dfe: ADD 00000dff: PUSH2 0x0776 00000e02: SWAP1 00000e03: PUSH2 0x2783 00000e06: JUMP 00000e07: JUMPDEST 00000e08: PUSH1 0x00 00000e0a: DUP1 00000e0b: SLOAD 00000e0c: PUSH1 0xff 00000e0e: NOT 00000e0f: AND 00000e10: PUSH1 0x01 00000e12: OR 00000e13: SWAP1 00000e14: SSTORE 00000e15: DUP1 00000e16: ISZERO 00000e17: PUSH2 0x0e2a 00000e1a: JUMPI 00000e1b: PUSH1 0x00 00000e1d: DUP1 00000e1e: SLOAD 00000e1f: PUSH2 0xff00 00000e22: NOT 00000e23: AND 00000e24: PUSH2 0x0100 00000e27: OR 00000e28: SWAP1 00000e29: SSTORE 00000e2a: JUMPDEST 00000e2b: PUSH2 0x0e33 00000e2e: DUP4 00000e2f: PUSH2 0x193a 00000e32: JUMP 00000e33: JUMPDEST 00000e34: PUSH1 0xca 00000e36: DUP1 00000e37: SLOAD 00000e38: PUSH1 0x01 00000e3a: PUSH1 0x01 00000e3c: PUSH1 0xa0 00000e3e: SHL 00000e3f: SUB 00000e40: NOT 00000e41: AND 00000e42: PUSH1 0x01 00000e44: PUSH1 0x01 00000e46: PUSH1 0xa0 00000e48: SHL 00000e49: SUB 00000e4a: DUP5 00000e4b: AND 00000e4c: OR 00000e4d: SWAP1 00000e4e: SSTORE 00000e4f: DUP1 00000e50: ISZERO 00000e51: PUSH2 0x0b0e 00000e54: JUMPI 00000e55: PUSH1 0x00 00000e57: DUP1 00000e58: SLOAD 00000e59: PUSH2 0xff00 00000e5c: NOT 00000e5d: AND 00000e5e: SWAP1 00000e5f: SSTORE 00000e60: PUSH1 0x40 00000e62: MLOAD 00000e63: PUSH1 0x01 00000e65: DUP2 00000e66: MSTORE 00000e67: PUSH32 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 00000e88: SWAP1 00000e89: PUSH1 0x20 00000e8b: ADD 00000e8c: PUSH1 0x40 00000e8e: MLOAD 00000e8f: DUP1 00000e90: SWAP2 00000e91: SUB 00000e92: SWAP1 00000e93: LOG1 00000e94: POP 00000e95: POP 00000e96: POP 00000e97: JUMP 00000e98: JUMPDEST 00000e99: PUSH1 0xca 00000e9b: SLOAD 00000e9c: PUSH1 0x00 00000e9e: SWAP1 00000e9f: PUSH1 0x01 00000ea1: PUSH1 0x01 00000ea3: PUSH1 0xa0 00000ea5: SHL 00000ea6: SUB 00000ea7: AND 00000ea8: CALLER 00000ea9: EQ 00000eaa: PUSH2 0x0ef5 00000ead: JUMPI 00000eae: PUSH1 0x40 00000eb0: MLOAD 00000eb1: PUSH3 0x461bcd 00000eb5: PUSH1 0xe5 00000eb7: SHL 00000eb8: DUP2 00000eb9: MSTORE 00000eba: PUSH1 0x20 00000ebc: PUSH1 0x04 00000ebe: DUP3 00000ebf: ADD 00000ec0: MSTORE 00000ec1: PUSH1 0x1c 00000ec3: PUSH1 0x24 00000ec5: DUP3 00000ec6: ADD 00000ec7: MSTORE 00000ec8: PUSH32 0x53656e646572206973206e6f742061204d65737361676550726f787900000000 00000ee9: PUSH1 0x44 00000eeb: DUP3 00000eec: ADD 00000eed: MSTORE 00000eee: PUSH1 0x64 00000ef0: ADD 00000ef1: PUSH2 0x0776 00000ef4: JUMP 00000ef5: JUMPDEST 00000ef6: PUSH1 0x01 00000ef8: PUSH1 0x01 00000efa: PUSH1 0xa0 00000efc: SHL 00000efd: SUB 00000efe: DUP5 00000eff: AND 00000f00: PUSH2 0x0f4b 00000f03: JUMPI 00000f04: PUSH1 0x40 00000f06: MLOAD 00000f07: PUSH3 0x461bcd 00000f0b: PUSH1 0xe5 00000f0d: SHL 00000f0e: DUP2 00000f0f: MSTORE 00000f10: PUSH1 0x20 00000f12: PUSH1 0x04 00000f14: DUP3 00000f15: ADD 00000f16: MSTORE 00000f17: PUSH1 0x18 00000f19: PUSH1 0x24 00000f1b: DUP3 00000f1c: ADD 00000f1d: MSTORE 00000f1e: PUSH32 0x4e6f64652061646472657373206d757374206265207365740000000000000000 00000f3f: PUSH1 0x44 00000f41: DUP3 00000f42: ADD 00000f43: MSTORE 00000f44: PUSH1 0x64 00000f46: ADD 00000f47: PUSH2 0x0776 00000f4a: JUMP 00000f4b: JUMPDEST 00000f4c: PUSH1 0x01 00000f4e: PUSH1 0x01 00000f50: PUSH1 0xa0 00000f52: SHL 00000f53: SUB 00000f54: DUP4 00000f55: AND 00000f56: PUSH1 0x00 00000f58: SWAP1 00000f59: DUP2 00000f5a: MSTORE 00000f5b: PUSH1 0xcd 00000f5d: PUSH1 0x20 00000f5f: SWAP1 00000f60: DUP2 00000f61: MSTORE 00000f62: PUSH1 0x40 00000f64: DUP1 00000f65: DUP4 00000f66: KECCAK256 00000f67: DUP9 00000f68: DUP5 00000f69: MSTORE 00000f6a: SWAP1 00000f6b: SWAP2 00000f6c: MSTORE 00000f6d: SWAP1 00000f6e: KECCAK256 00000f6f: SLOAD 00000f70: PUSH1 0xff 00000f72: AND 00000f73: PUSH2 0x0f7d 00000f76: JUMPI 00000f77: POP 00000f78: DUP1 00000f79: PUSH2 0x0da9 00000f7c: JUMP 00000f7d: JUMPDEST 00000f7e: PUSH1 0x00 00000f80: PUSH2 0x0f89 00000f83: DUP4 00000f84: GASPRICE 00000f85: PUSH2 0x27e7 00000f88: JUMP 00000f89: JUMPDEST 00000f8a: PUSH1 0x01 00000f8c: PUSH1 0x01 00000f8e: PUSH1 0xa0 00000f90: SHL 00000f91: SUB 00000f92: DUP6 00000f93: AND 00000f94: PUSH1 0x00 00000f96: SWAP1 00000f97: DUP2 00000f98: MSTORE 00000f99: PUSH1 0xcc 00000f9b: PUSH1 0x20 00000f9d: SWAP1 00000f9e: DUP2 00000f9f: MSTORE 00000fa0: PUSH1 0x40 00000fa2: DUP1 00000fa3: DUP4 00000fa4: KECCAK256 00000fa5: DUP11 00000fa6: DUP5 00000fa7: MSTORE 00000fa8: SWAP1 00000fa9: SWAP2 00000faa: MSTORE 00000fab: SWAP1 00000fac: KECCAK256 00000fad: SLOAD 00000fae: SWAP1 00000faf: SWAP2 00000fb0: POP 00000fb1: DUP2 00000fb2: GT 00000fb3: ISZERO 00000fb4: PUSH2 0x0fdd 00000fb7: JUMPI 00000fb8: POP 00000fb9: PUSH1 0x01 00000fbb: PUSH1 0x01 00000fbd: PUSH1 0xa0 00000fbf: SHL 00000fc0: SUB 00000fc1: DUP4 00000fc2: AND 00000fc3: PUSH1 0x00 00000fc5: SWAP1 00000fc6: DUP2 00000fc7: MSTORE 00000fc8: PUSH1 0xcc 00000fca: PUSH1 0x20 00000fcc: SWAP1 00000fcd: DUP2 00000fce: MSTORE 00000fcf: PUSH1 0x40 00000fd1: DUP1 00000fd2: DUP4 00000fd3: KECCAK256 00000fd4: DUP9 00000fd5: DUP5 00000fd6: MSTORE 00000fd7: SWAP1 00000fd8: SWAP2 00000fd9: MSTORE 00000fda: SWAP1 00000fdb: KECCAK256 00000fdc: SLOAD 00000fdd: JUMPDEST 00000fde: PUSH1 0x01 00000fe0: PUSH1 0x01 00000fe2: PUSH1 0xa0 00000fe4: SHL 00000fe5: SUB 00000fe6: DUP5 00000fe7: AND 00000fe8: PUSH1 0x00 00000fea: SWAP1 00000feb: DUP2 00000fec: MSTORE 00000fed: PUSH1 0xcc 00000fef: PUSH1 0x20 00000ff1: SWAP1 00000ff2: DUP2 00000ff3: MSTORE 00000ff4: PUSH1 0x40 00000ff6: DUP1 00000ff7: DUP4 00000ff8: KECCAK256 00000ff9: DUP10 00000ffa: DUP5 00000ffb: MSTORE 00000ffc: SWAP1 00000ffd: SWAP2 00000ffe: MSTORE 00000fff: SWAP1 00001000: KECCAK256 00001001: SLOAD 00001002: PUSH2 0x100c 00001005: SWAP1 00001006: DUP3 00001007: SWAP1 00001008: PUSH2 0x27fe 0000100b: JUMP 0000100c: JUMPDEST 0000100d: PUSH1 0x01 0000100f: PUSH1 0x01 00001011: PUSH1 0xa0 00001013: SHL 00001014: SUB 00001015: DUP6 00001016: AND 00001017: PUSH1 0x00 00001019: SWAP1 0000101a: DUP2 0000101b: MSTORE 0000101c: PUSH1 0xcc 0000101e: PUSH1 0x20 00001020: SWAP1 00001021: DUP2 00001022: MSTORE 00001023: PUSH1 0x40 00001025: DUP1 00001026: DUP4 00001027: KECCAK256 00001028: DUP11 00001029: DUP5 0000102a: MSTORE 0000102b: SWAP1 0000102c: SWAP2 0000102d: MSTORE 0000102e: DUP2 0000102f: KECCAK256 00001030: SWAP2 00001031: SWAP1 00001032: SWAP2 00001033: SSTORE 00001034: PUSH2 0x1040 00001037: SWAP1 00001038: DUP8 00001039: SWAP1 0000103a: DUP7 0000103b: SWAP1 0000103c: PUSH2 0x1c75 0000103f: JUMP 00001040: JUMPDEST 00001041: PUSH2 0x10dd 00001044: JUMPI 00001045: PUSH1 0x01 00001047: PUSH1 0x01 00001049: PUSH1 0xa0 0000104b: SHL 0000104c: SUB 0000104d: DUP1 0000104e: DUP6 0000104f: AND 00001050: PUSH1 0x00 00001052: SWAP1 00001053: DUP2 00001054: MSTORE 00001055: PUSH1 0xcd 00001057: PUSH1 0x20 00001059: SWAP1 0000105a: DUP2 0000105b: MSTORE 0000105c: PUSH1 0x40 0000105e: DUP1 0000105f: DUP4 00001060: KECCAK256 00001061: DUP11 00001062: DUP5 00001063: MSTORE 00001064: SWAP1 00001065: SWAP2 00001066: MSTORE 00001067: SWAP1 00001068: KECCAK256 00001069: DUP1 0000106a: SLOAD 0000106b: PUSH1 0xff 0000106d: NOT 0000106e: AND 0000106f: SWAP1 00001070: SSTORE 00001071: PUSH1 0xca 00001073: SLOAD 00001074: AND 00001075: PUSH4 0x94489202 0000107a: DUP8 0000107b: PUSH2 0x1083 0000107e: DUP2 0000107f: PUSH2 0x13b5 00001082: JUMP 00001083: JUMPDEST 00001084: PUSH2 0x108c 00001087: DUP9 00001088: PUSH2 0x1d0e 0000108b: JUMP 0000108c: JUMPDEST 0000108d: PUSH1 0x40 0000108f: MLOAD 00001090: DUP5 00001091: PUSH4 0xffffffff 00001096: AND 00001097: PUSH1 0xe0 00001099: SHL 0000109a: DUP2 0000109b: MSTORE 0000109c: PUSH1 0x04 0000109e: ADD 0000109f: PUSH2 0x10aa 000010a2: SWAP4 000010a3: SWAP3 000010a4: SWAP2 000010a5: SWAP1 000010a6: PUSH2 0x2861 000010a9: JUMP 000010aa: JUMPDEST 000010ab: PUSH1 0x00 000010ad: PUSH1 0x40 000010af: MLOAD 000010b0: DUP1 000010b1: DUP4 000010b2: SUB 000010b3: DUP2 000010b4: PUSH1 0x00 000010b6: DUP8 000010b7: DUP1 000010b8: EXTCODESIZE 000010b9: ISZERO 000010ba: DUP1 000010bb: ISZERO 000010bc: PUSH2 0x10c4 000010bf: JUMPI 000010c0: PUSH1 0x00 000010c2: DUP1 000010c3: REVERT 000010c4: JUMPDEST 000010c5: POP 000010c6: GAS 000010c7: CALL 000010c8: ISZERO 000010c9: DUP1 000010ca: ISZERO 000010cb: PUSH2 0x10d8 000010ce: JUMPI 000010cf: RETURNDATASIZE 000010d0: PUSH1 0x00 000010d2: DUP1 000010d3: RETURNDATACOPY 000010d4: RETURNDATASIZE 000010d5: PUSH1 0x00 000010d7: REVERT 000010d8: JUMPDEST 000010d9: POP 000010da: POP 000010db: POP 000010dc: POP 000010dd: JUMPDEST 000010de: PUSH2 0x10f0 000010e1: PUSH1 0x01 000010e3: PUSH1 0x01 000010e5: PUSH1 0xa0 000010e7: SHL 000010e8: SUB 000010e9: DUP7 000010ea: AND 000010eb: DUP3 000010ec: PUSH2 0x1d1b 000010ef: JUMP 000010f0: JUMPDEST 000010f1: GASPRICE 000010f2: DUP2 000010f3: PUSH2 0x10fc 000010f6: DUP6 000010f7: DUP4 000010f8: PUSH2 0x27e7 000010fb: JUMP 000010fc: JUMPDEST 000010fd: PUSH2 0x1106 00001100: SWAP2 00001101: SWAP1 00001102: PUSH2 0x27fe 00001105: JUMP 00001106: JUMPDEST 00001107: PUSH2 0x1110 0000110a: SWAP2 0000110b: SWAP1 0000110c: PUSH2 0x2894 0000110f: JUMP 00001110: JUMPDEST 00001111: SWAP7 00001112: SWAP6 00001113: POP 00001114: POP 00001115: POP 00001116: POP 00001117: POP 00001118: POP 00001119: JUMP 0000111a: JUMPDEST 0000111b: PUSH1 0x00 0000111d: PUSH2 0x115b 00001120: DUP4 00001121: DUP4 00001122: DUP1 00001123: DUP1 00001124: PUSH1 0x1f 00001126: ADD 00001127: PUSH1 0x20 00001129: DUP1 0000112a: SWAP2 0000112b: DIV 0000112c: MUL 0000112d: PUSH1 0x20 0000112f: ADD 00001130: PUSH1 0x40 00001132: MLOAD 00001133: SWAP1 00001134: DUP2 00001135: ADD 00001136: PUSH1 0x40 00001138: MSTORE 00001139: DUP1 0000113a: SWAP4 0000113b: SWAP3 0000113c: SWAP2 0000113d: SWAP1 0000113e: DUP2 0000113f: DUP2 00001140: MSTORE 00001141: PUSH1 0x20 00001143: ADD 00001144: DUP4 00001145: DUP4 00001146: DUP1 00001147: DUP3 00001148: DUP5 00001149: CALLDATACOPY 0000114a: PUSH1 0x00 0000114c: SWAP3 0000114d: ADD 0000114e: SWAP2 0000114f: SWAP1 00001150: SWAP2 00001151: MSTORE 00001152: POP 00001153: PUSH2 0x1c45 00001156: SWAP3 00001157: POP 00001158: POP 00001159: POP 0000115a: JUMP 0000115b: JUMPDEST 0000115c: SWAP1 0000115d: POP 0000115e: PUSH2 0x1175 00001161: PUSH1 0x00 00001163: DUP1 00001164: MLOAD 00001165: PUSH1 0x20 00001167: PUSH2 0x2a15 0000116a: DUP4 0000116b: CODECOPY 0000116c: DUP2 0000116d: MLOAD 0000116e: SWAP2 0000116f: MSTORE 00001170: CALLER 00001171: PUSH2 0x1459 00001174: JUMP 00001175: JUMPDEST 00001176: DUP1 00001177: PUSH2 0x1185 0000117a: JUMPI 0000117b: POP 0000117c: PUSH2 0x1185 0000117f: CALLER 00001180: DUP3 00001181: PUSH2 0x0ca2 00001184: JUMP 00001185: JUMPDEST 00001186: PUSH2 0x11c9 00001189: JUMPI 0000118a: PUSH1 0x40 0000118c: MLOAD 0000118d: PUSH3 0x461bcd 00001191: PUSH1 0xe5 00001193: SHL 00001194: DUP2 00001195: MSTORE 00001196: PUSH1 0x20 00001198: PUSH1 0x04 0000119a: DUP3 0000119b: ADD 0000119c: MSTORE 0000119d: PUSH1 0x15 0000119f: PUSH1 0x24 000011a1: DUP3 000011a2: ADD 000011a3: MSTORE 000011a4: PUSH21 0x2737ba1030baba3437b934bd32b21031b0b63632b9 000011ba: PUSH1 0x59 000011bc: SHL 000011bd: PUSH1 0x44 000011bf: DUP3 000011c0: ADD 000011c1: MSTORE 000011c2: PUSH1 0x64 000011c4: ADD 000011c5: PUSH2 0x0776 000011c8: JUMP 000011c9: JUMPDEST 000011ca: PUSH1 0x00 000011cc: DUP2 000011cd: DUP2 000011ce: MSTORE 000011cf: PUSH1 0xcb 000011d1: PUSH1 0x20 000011d3: MSTORE 000011d4: PUSH1 0x40 000011d6: SWAP1 000011d7: KECCAK256 000011d8: SLOAD 000011d9: PUSH1 0x01 000011db: PUSH1 0x01 000011dd: PUSH1 0xa0 000011df: SHL 000011e0: SUB 000011e1: AND 000011e2: PUSH2 0x1226 000011e5: JUMPI 000011e6: PUSH1 0x40 000011e8: MLOAD 000011e9: PUSH3 0x461bcd 000011ed: PUSH1 0xe5 000011ef: SHL 000011f0: DUP2 000011f1: MSTORE 000011f2: PUSH1 0x20 000011f4: PUSH1 0x04 000011f6: DUP3 000011f7: ADD 000011f8: MSTORE 000011f9: PUSH1 0x16 000011fb: PUSH1 0x24 000011fd: DUP3 000011fe: ADD 000011ff: MSTORE 00001200: PUSH22 0x14d2d053114818da185a5b881a5cc81b9bdd081cd95d 00001217: PUSH1 0x52 00001219: SHL 0000121a: PUSH1 0x44 0000121c: DUP3 0000121d: ADD 0000121e: MSTORE 0000121f: PUSH1 0x64 00001221: ADD 00001222: PUSH2 0x0776 00001225: JUMP 00001226: JUMPDEST 00001227: PUSH1 0x00 00001229: SWAP1 0000122a: DUP2 0000122b: MSTORE 0000122c: PUSH1 0xcb 0000122e: PUSH1 0x20 00001230: MSTORE 00001231: PUSH1 0x40 00001233: SWAP1 00001234: KECCAK256 00001235: DUP1 00001236: SLOAD 00001237: PUSH1 0x01 00001239: PUSH1 0x01 0000123b: PUSH1 0xa0 0000123d: SHL 0000123e: SUB 0000123f: NOT 00001240: AND 00001241: SWAP1 00001242: SSTORE 00001243: POP 00001244: POP 00001245: JUMP 00001246: JUMPDEST 00001247: PUSH2 0x1270 0000124a: PUSH32 0x96e3fc3be15159903e053027cff8a23f39a990e0194abcd8ac1cf1b355b8b93c 0000126b: CALLER 0000126c: PUSH2 0x1459 0000126f: JUMP 00001270: JUMPDEST 00001271: PUSH2 0x12bc 00001274: JUMPI 00001275: PUSH1 0x40 00001277: MLOAD 00001278: PUSH3 0x461bcd 0000127c: PUSH1 0xe5 0000127e: SHL 0000127f: DUP2 00001280: MSTORE 00001281: PUSH1 0x20 00001283: PUSH1 0x04 00001285: DUP3 00001286: ADD 00001287: DUP2 00001288: SWAP1 00001289: MSTORE 0000128a: PUSH1 0x24 0000128c: DUP3 0000128d: ADD 0000128e: MSTORE 0000128f: PUSH32 0x434f4e5354414e545f5345545445525f524f4c45206973207265717569726564 000012b0: PUSH1 0x44 000012b2: DUP3 000012b3: ADD 000012b4: MSTORE 000012b5: PUSH1 0x64 000012b7: ADD 000012b8: PUSH2 0x0776 000012bb: JUMP 000012bc: JUMPDEST 000012bd: PUSH1 0xce 000012bf: SLOAD 000012c0: PUSH1 0x40 000012c2: DUP1 000012c3: MLOAD 000012c4: SWAP2 000012c5: DUP3 000012c6: MSTORE 000012c7: PUSH1 0x20 000012c9: DUP3 000012ca: ADD 000012cb: DUP4 000012cc: SWAP1 000012cd: MSTORE 000012ce: PUSH32 0x331f224b2912576029359714fd8a4f953651fb48b042c6c23f8da99bab035a43 000012ef: SWAP2 000012f0: ADD 000012f1: PUSH1 0x40 000012f3: MLOAD 000012f4: DUP1 000012f5: SWAP2 000012f6: SUB 000012f7: SWAP1 000012f8: LOG1 000012f9: PUSH1 0xce 000012fb: SSTORE 000012fc: JUMP 000012fd: JUMPDEST 000012fe: PUSH1 0x00 00001300: GASPRICE 00001301: PUSH1 0x00 00001303: SUB 00001304: PUSH2 0x1346 00001307: JUMPI 00001308: PUSH1 0x40 0000130a: MLOAD 0000130b: PUSH3 0x461bcd 0000130f: PUSH1 0xe5 00001311: SHL 00001312: DUP2 00001313: MSTORE 00001314: PUSH1 0x20 00001316: PUSH1 0x04 00001318: DUP3 00001319: ADD 0000131a: MSTORE 0000131b: PUSH1 0x14 0000131d: PUSH1 0x24 0000131f: DUP3 00001320: ADD 00001321: MSTORE 00001322: PUSH20 0x11d85cc81c1c9a58d9481a5cc81b9bdd081cd95d 00001337: PUSH1 0x62 00001339: SHL 0000133a: PUSH1 0x44 0000133c: DUP3 0000133d: ADD 0000133e: MSTORE 0000133f: PUSH1 0x64 00001341: ADD 00001342: PUSH2 0x0776 00001345: JUMP 00001346: JUMPDEST 00001347: PUSH1 0x00 00001349: PUSH2 0x1350 0000134c: PUSH2 0x1e34 0000134f: JUMP 00001350: JUMPDEST 00001351: PUSH1 0x01 00001353: PUSH1 0x01 00001355: PUSH1 0xa0 00001357: SHL 00001358: SUB 00001359: DUP5 0000135a: AND 0000135b: PUSH1 0x00 0000135d: SWAP1 0000135e: DUP2 0000135f: MSTORE 00001360: PUSH1 0xcc 00001362: PUSH1 0x20 00001364: SWAP1 00001365: DUP2 00001366: MSTORE 00001367: PUSH1 0x40 00001369: DUP1 0000136a: DUP4 0000136b: KECCAK256 0000136c: DUP9 0000136d: DUP5 0000136e: MSTORE 0000136f: SWAP1 00001370: SWAP2 00001371: MSTORE 00001372: SWAP1 00001373: KECCAK256 00001374: SLOAD 00001375: SWAP1 00001376: SWAP2 00001377: POP 00001378: DUP2 00001379: GT 0000137a: PUSH2 0x1387 0000137d: JUMPI 0000137e: PUSH1 0x00 00001380: SWAP2 00001381: POP 00001382: POP 00001383: PUSH2 0x0717 00001386: JUMP 00001387: JUMPDEST 00001388: PUSH1 0x01 0000138a: PUSH1 0x01 0000138c: PUSH1 0xa0 0000138e: SHL 0000138f: SUB 00001390: DUP4 00001391: AND 00001392: PUSH1 0x00 00001394: SWAP1 00001395: DUP2 00001396: MSTORE 00001397: PUSH1 0xcc 00001399: PUSH1 0x20 0000139b: SWAP1 0000139c: DUP2 0000139d: MSTORE 0000139e: PUSH1 0x40 000013a0: DUP1 000013a1: DUP4 000013a2: KECCAK256 000013a3: DUP8 000013a4: DUP5 000013a5: MSTORE 000013a6: SWAP1 000013a7: SWAP2 000013a8: MSTORE 000013a9: SWAP1 000013aa: KECCAK256 000013ab: SLOAD 000013ac: PUSH2 0x0da9 000013af: SWAP1 000013b0: DUP3 000013b1: PUSH2 0x27fe 000013b4: JUMP 000013b5: JUMPDEST 000013b6: PUSH1 0x00 000013b8: DUP2 000013b9: DUP2 000013ba: MSTORE 000013bb: PUSH1 0xcb 000013bd: PUSH1 0x20 000013bf: MSTORE 000013c0: PUSH1 0x40 000013c2: DUP2 000013c3: KECCAK256 000013c4: SLOAD 000013c5: PUSH1 0x01 000013c7: PUSH1 0x01 000013c9: PUSH1 0xa0 000013cb: SHL 000013cc: SUB 000013cd: AND 000013ce: PUSH2 0x1425 000013d1: JUMPI 000013d2: PUSH1 0x40 000013d4: MLOAD 000013d5: PUSH3 0x461bcd 000013d9: PUSH1 0xe5 000013db: SHL 000013dc: DUP2 000013dd: MSTORE 000013de: PUSH1 0x20 000013e0: PUSH1 0x04 000013e2: DUP3 000013e3: ADD 000013e4: MSTORE 000013e5: PUSH1 0x24 000013e7: DUP1 000013e8: DUP3 000013e9: ADD 000013ea: MSTORE 000013eb: PUSH32 0x44657374696e6174696f6e20636f6e7472616374206d75737420626520646566 0000140c: PUSH1 0x44 0000140e: DUP3 0000140f: ADD 00001410: MSTORE 00001411: PUSH4 0x1a5b9959 00001416: PUSH1 0xe2 00001418: SHL 00001419: PUSH1 0x64 0000141b: DUP3 0000141c: ADD 0000141d: MSTORE 0000141e: PUSH1 0x84 00001420: ADD 00001421: PUSH2 0x0776 00001424: JUMP 00001425: JUMPDEST 00001426: POP 00001427: PUSH1 0x00 00001429: SWAP1 0000142a: DUP2 0000142b: MSTORE 0000142c: PUSH1 0xcb 0000142e: PUSH1 0x20 00001430: MSTORE 00001431: PUSH1 0x40 00001433: SWAP1 00001434: KECCAK256 00001435: SLOAD 00001436: PUSH1 0x01 00001438: PUSH1 0x01 0000143a: PUSH1 0xa0 0000143c: SHL 0000143d: SUB 0000143e: AND 0000143f: SWAP1 00001440: JUMP 00001441: JUMPDEST 00001442: PUSH1 0x00 00001444: DUP3 00001445: DUP2 00001446: MSTORE 00001447: PUSH1 0x97 00001449: PUSH1 0x20 0000144b: MSTORE 0000144c: PUSH1 0x40 0000144e: DUP2 0000144f: KECCAK256 00001450: PUSH2 0x0ae2 00001453: SWAP1 00001454: DUP4 00001455: PUSH2 0x1e63 00001458: JUMP 00001459: JUMPDEST 0000145a: PUSH1 0x00 0000145c: SWAP2 0000145d: DUP3 0000145e: MSTORE 0000145f: PUSH1 0x65 00001461: PUSH1 0x20 00001463: SWAP1 00001464: DUP2 00001465: MSTORE 00001466: PUSH1 0x40 00001468: DUP1 00001469: DUP5 0000146a: KECCAK256 0000146b: PUSH1 0x01 0000146d: PUSH1 0x01 0000146f: PUSH1 0xa0 00001471: SHL 00001472: SUB 00001473: SWAP4 00001474: SWAP1 00001475: SWAP4 00001476: AND 00001477: DUP5 00001478: MSTORE 00001479: SWAP2 0000147a: SWAP1 0000147b: MSTORE 0000147c: SWAP1 0000147d: KECCAK256 0000147e: SLOAD 0000147f: PUSH1 0xff 00001481: AND 00001482: SWAP1 00001483: JUMP 00001484: JUMPDEST 00001485: PUSH1 0x00 00001487: PUSH2 0x14c5 0000148a: DUP5 0000148b: DUP5 0000148c: DUP1 0000148d: DUP1 0000148e: PUSH1 0x1f 00001490: ADD 00001491: PUSH1 0x20 00001493: DUP1 00001494: SWAP2 00001495: DIV 00001496: MUL 00001497: PUSH1 0x20 00001499: ADD 0000149a: PUSH1 0x40 0000149c: MLOAD 0000149d: SWAP1 0000149e: DUP2 0000149f: ADD 000014a0: PUSH1 0x40 000014a2: MSTORE 000014a3: DUP1 000014a4: SWAP4 000014a5: SWAP3 000014a6: SWAP2 000014a7: SWAP1 000014a8: DUP2 000014a9: DUP2 000014aa: MSTORE 000014ab: PUSH1 0x20 000014ad: ADD 000014ae: DUP4 000014af: DUP4 000014b0: DUP1 000014b1: DUP3 000014b2: DUP5 000014b3: CALLDATACOPY 000014b4: PUSH1 0x00 000014b6: SWAP3 000014b7: ADD 000014b8: SWAP2 000014b9: SWAP1 000014ba: SWAP2 000014bb: MSTORE 000014bc: POP 000014bd: PUSH2 0x1c45 000014c0: SWAP3 000014c1: POP 000014c2: POP 000014c3: POP 000014c4: JUMP 000014c5: JUMPDEST 000014c6: CALLER 000014c7: PUSH1 0x00 000014c9: SWAP1 000014ca: DUP2 000014cb: MSTORE 000014cc: PUSH1 0xcc 000014ce: PUSH1 0x20 000014d0: SWAP1 000014d1: DUP2 000014d2: MSTORE 000014d3: PUSH1 0x40 000014d5: DUP1 000014d6: DUP4 000014d7: KECCAK256 000014d8: DUP5 000014d9: DUP5 000014da: MSTORE 000014db: SWAP1 000014dc: SWAP2 000014dd: MSTORE 000014de: SWAP1 000014df: KECCAK256 000014e0: SLOAD 000014e1: SWAP1 000014e2: SWAP2 000014e3: POP 000014e4: DUP3 000014e5: GT 000014e6: ISZERO 000014e7: PUSH2 0x1527 000014ea: JUMPI 000014eb: PUSH1 0x40 000014ed: MLOAD 000014ee: PUSH3 0x461bcd 000014f2: PUSH1 0xe5 000014f4: SHL 000014f5: DUP2 000014f6: MSTORE 000014f7: PUSH1 0x20 000014f9: PUSH1 0x04 000014fb: DUP3 000014fc: ADD 000014fd: MSTORE 000014fe: PUSH1 0x12 00001500: PUSH1 0x24 00001502: DUP3 00001503: ADD 00001504: MSTORE 00001505: PUSH18 0x42616c616e636520697320746f6f206c6f77 00001518: PUSH1 0x70 0000151a: SHL 0000151b: PUSH1 0x44 0000151d: DUP3 0000151e: ADD 0000151f: MSTORE 00001520: PUSH1 0x64 00001522: ADD 00001523: PUSH2 0x0776 00001526: JUMP 00001527: JUMPDEST 00001528: PUSH1 0xca 0000152a: PUSH1 0x00 0000152c: SWAP1 0000152d: SLOAD 0000152e: SWAP1 0000152f: PUSH2 0x0100 00001532: EXP 00001533: SWAP1 00001534: DIV 00001535: PUSH1 0x01 00001537: PUSH1 0x01 00001539: PUSH1 0xa0 0000153b: SHL 0000153c: SUB 0000153d: AND 0000153e: PUSH1 0x01 00001540: PUSH1 0x01 00001542: PUSH1 0xa0 00001544: SHL 00001545: SUB 00001546: AND 00001547: PUSH4 0x1cf5379d 0000154c: PUSH1 0x40 0000154e: MLOAD 0000154f: DUP2 00001550: PUSH4 0xffffffff 00001555: AND 00001556: PUSH1 0xe0 00001558: SHL 00001559: DUP2 0000155a: MSTORE 0000155b: PUSH1 0x04 0000155d: ADD 0000155e: PUSH1 0x20 00001560: PUSH1 0x40 00001562: MLOAD 00001563: DUP1 00001564: DUP4 00001565: SUB 00001566: DUP2 00001567: DUP7 00001568: GAS 00001569: STATICCALL 0000156a: ISZERO 0000156b: DUP1 0000156c: ISZERO 0000156d: PUSH2 0x157a 00001570: JUMPI 00001571: RETURNDATASIZE 00001572: PUSH1 0x00 00001574: DUP1 00001575: RETURNDATACOPY 00001576: RETURNDATASIZE 00001577: PUSH1 0x00 00001579: REVERT 0000157a: JUMPDEST 0000157b: POP 0000157c: POP 0000157d: POP 0000157e: POP 0000157f: PUSH1 0x40 00001581: MLOAD 00001582: RETURNDATASIZE 00001583: PUSH1 0x1f 00001585: NOT 00001586: PUSH1 0x1f 00001588: DUP3 00001589: ADD 0000158a: AND 0000158b: DUP3 0000158c: ADD 0000158d: DUP1 0000158e: PUSH1 0x40 00001590: MSTORE 00001591: POP 00001592: DUP2 00001593: ADD 00001594: SWAP1 00001595: PUSH2 0x159e 00001598: SWAP2 00001599: SWAP1 0000159a: PUSH2 0x2761 0000159d: JUMP 0000159e: JUMPDEST 0000159f: ISZERO 000015a0: PUSH2 0x15e4 000015a3: JUMPI 000015a4: PUSH1 0x40 000015a6: MLOAD 000015a7: PUSH3 0x461bcd 000015ab: PUSH1 0xe5 000015ad: SHL 000015ae: DUP2 000015af: MSTORE 000015b0: PUSH1 0x20 000015b2: PUSH1 0x04 000015b4: DUP3 000015b5: ADD 000015b6: MSTORE 000015b7: PUSH1 0x16 000015b9: PUSH1 0x24 000015bb: DUP3 000015bc: ADD 000015bd: MSTORE 000015be: PUSH22 0x4d65737361676520697320696e2070726f6772657373 000015d5: PUSH1 0x50 000015d7: SHL 000015d8: PUSH1 0x44 000015da: DUP3 000015db: ADD 000015dc: MSTORE 000015dd: PUSH1 0x64 000015df: ADD 000015e0: PUSH2 0x0776 000015e3: JUMP 000015e4: JUMPDEST 000015e5: CALLER 000015e6: PUSH1 0x00 000015e8: SWAP1 000015e9: DUP2 000015ea: MSTORE 000015eb: PUSH1 0xcc 000015ed: PUSH1 0x20 000015ef: SWAP1 000015f0: DUP2 000015f1: MSTORE 000015f2: PUSH1 0x40 000015f4: DUP1 000015f5: DUP4 000015f6: KECCAK256 000015f7: DUP5 000015f8: DUP5 000015f9: MSTORE 000015fa: SWAP1 000015fb: SWAP2 000015fc: MSTORE 000015fd: SWAP1 000015fe: KECCAK256 000015ff: SLOAD 00001600: PUSH2 0x160a 00001603: SWAP1 00001604: DUP4 00001605: SWAP1 00001606: PUSH2 0x27fe 00001609: JUMP 0000160a: JUMPDEST 0000160b: CALLER 0000160c: PUSH1 0x00 0000160e: DUP2 0000160f: DUP2 00001610: MSTORE 00001611: PUSH1 0xcc 00001613: PUSH1 0x20 00001615: SWAP1 00001616: DUP2 00001617: MSTORE 00001618: PUSH1 0x40 0000161a: DUP1 0000161b: DUP4 0000161c: KECCAK256 0000161d: DUP7 0000161e: DUP5 0000161f: MSTORE 00001620: SWAP1 00001621: SWAP2 00001622: MSTORE 00001623: DUP2 00001624: KECCAK256 00001625: SWAP3 00001626: SWAP1 00001627: SWAP3 00001628: SSTORE 00001629: PUSH2 0x1634 0000162c: SWAP2 0000162d: DUP4 0000162e: SWAP2 0000162f: SWAP1 00001630: PUSH2 0x1c75 00001633: JUMP 00001634: JUMPDEST 00001635: ISZERO 00001636: DUP1 00001637: ISZERO 00001638: PUSH2 0x165b 0000163b: JUMPI 0000163c: POP 0000163d: CALLER 0000163e: PUSH1 0x00 00001640: SWAP1 00001641: DUP2 00001642: MSTORE 00001643: PUSH1 0xcd 00001645: PUSH1 0x20 00001647: SWAP1 00001648: DUP2 00001649: MSTORE 0000164a: PUSH1 0x40 0000164c: DUP1 0000164d: DUP4 0000164e: KECCAK256 0000164f: DUP5 00001650: DUP5 00001651: MSTORE 00001652: SWAP1 00001653: SWAP2 00001654: MSTORE 00001655: SWAP1 00001656: KECCAK256 00001657: SLOAD 00001658: PUSH1 0xff 0000165a: AND 0000165b: JUMPDEST 0000165c: ISZERO 0000165d: PUSH2 0x16f7 00001660: JUMPI 00001661: CALLER 00001662: PUSH1 0x00 00001664: SWAP1 00001665: DUP2 00001666: MSTORE 00001667: PUSH1 0xcd 00001669: PUSH1 0x20 0000166b: SWAP1 0000166c: DUP2 0000166d: MSTORE 0000166e: PUSH1 0x40 00001670: DUP1 00001671: DUP4 00001672: KECCAK256 00001673: DUP5 00001674: DUP5 00001675: MSTORE 00001676: SWAP1 00001677: SWAP2 00001678: MSTORE 00001679: SWAP1 0000167a: KECCAK256 0000167b: DUP1 0000167c: SLOAD 0000167d: PUSH1 0xff 0000167f: NOT 00001680: AND 00001681: SWAP1 00001682: SSTORE 00001683: PUSH1 0xca 00001685: SLOAD 00001686: PUSH1 0x01 00001688: PUSH1 0x01 0000168a: PUSH1 0xa0 0000168c: SHL 0000168d: SUB 0000168e: AND 0000168f: PUSH4 0x94489202 00001694: DUP3 00001695: PUSH2 0x169d 00001698: DUP2 00001699: PUSH2 0x13b5 0000169c: JUMP 0000169d: JUMPDEST 0000169e: PUSH2 0x16a6 000016a1: CALLER 000016a2: PUSH2 0x1d0e 000016a5: JUMP 000016a6: JUMPDEST 000016a7: PUSH1 0x40 000016a9: MLOAD 000016aa: DUP5 000016ab: PUSH4 0xffffffff 000016b0: AND 000016b1: PUSH1 0xe0 000016b3: SHL 000016b4: DUP2 000016b5: MSTORE 000016b6: PUSH1 0x04 000016b8: ADD 000016b9: PUSH2 0x16c4 000016bc: SWAP4 000016bd: SWAP3 000016be: SWAP2 000016bf: SWAP1 000016c0: PUSH2 0x2861 000016c3: JUMP 000016c4: JUMPDEST 000016c5: PUSH1 0x00 000016c7: PUSH1 0x40 000016c9: MLOAD 000016ca: DUP1 000016cb: DUP4 000016cc: SUB 000016cd: DUP2 000016ce: PUSH1 0x00 000016d0: DUP8 000016d1: DUP1 000016d2: EXTCODESIZE 000016d3: ISZERO 000016d4: DUP1 000016d5: ISZERO 000016d6: PUSH2 0x16de 000016d9: JUMPI 000016da: PUSH1 0x00 000016dc: DUP1 000016dd: REVERT 000016de: JUMPDEST 000016df: POP 000016e0: GAS 000016e1: CALL 000016e2: ISZERO 000016e3: DUP1 000016e4: ISZERO 000016e5: PUSH2 0x16f2 000016e8: JUMPI 000016e9: RETURNDATASIZE 000016ea: PUSH1 0x00 000016ec: DUP1 000016ed: RETURNDATACOPY 000016ee: RETURNDATASIZE 000016ef: PUSH1 0x00 000016f1: REVERT 000016f2: JUMPDEST 000016f3: POP 000016f4: POP 000016f5: POP 000016f6: POP 000016f7: JUMPDEST 000016f8: PUSH2 0x1701 000016fb: CALLER 000016fc: DUP4 000016fd: PUSH2 0x1d1b 00001700: JUMP 00001701: JUMPDEST 00001702: POP 00001703: POP 00001704: POP 00001705: POP 00001706: JUMP 00001707: JUMPDEST 00001708: PUSH1 0xc9 0000170a: SLOAD 0000170b: PUSH1 0x40 0000170d: MLOAD 0000170e: PUSH4 0x35817773 00001713: PUSH1 0xe0 00001715: SHL 00001716: DUP2 00001717: MSTORE 00001718: PUSH1 0x20 0000171a: PUSH1 0x04 0000171c: DUP3 0000171d: ADD 0000171e: MSTORE 0000171f: PUSH1 0x0f 00001721: PUSH1 0x24 00001723: DUP3 00001724: ADD 00001725: MSTORE 00001726: PUSH15 0x14d8da185a5b9cd25b9d195c9b985b 00001736: PUSH1 0x8a 00001738: SHL 00001739: PUSH1 0x44 0000173b: DUP3 0000173c: ADD 0000173d: MSTORE 0000173e: PUSH1 0x00 00001740: SWAP2 00001741: DUP3 00001742: SWAP2 00001743: PUSH1 0x01 00001745: PUSH1 0x01 00001747: PUSH1 0xa0 00001749: SHL 0000174a: SUB 0000174b: SWAP1 0000174c: SWAP2 0000174d: AND 0000174e: SWAP1 0000174f: PUSH4 0x35817773 00001754: SWAP1 00001755: PUSH1 0x64 00001757: ADD 00001758: PUSH1 0x20 0000175a: PUSH1 0x40 0000175c: MLOAD 0000175d: DUP1 0000175e: DUP4 0000175f: SUB 00001760: DUP2 00001761: DUP7 00001762: GAS 00001763: STATICCALL 00001764: ISZERO 00001765: DUP1 00001766: ISZERO 00001767: PUSH2 0x1774 0000176a: JUMPI 0000176b: RETURNDATASIZE 0000176c: PUSH1 0x00 0000176e: DUP1 0000176f: RETURNDATACOPY 00001770: RETURNDATASIZE 00001771: PUSH1 0x00 00001773: REVERT 00001774: JUMPDEST 00001775: POP 00001776: POP 00001777: POP 00001778: POP 00001779: PUSH1 0x40 0000177b: MLOAD 0000177c: RETURNDATASIZE 0000177d: PUSH1 0x1f 0000177f: NOT 00001780: PUSH1 0x1f 00001782: DUP3 00001783: ADD 00001784: AND 00001785: DUP3 00001786: ADD 00001787: DUP1 00001788: PUSH1 0x40 0000178a: MSTORE 0000178b: POP 0000178c: DUP2 0000178d: ADD 0000178e: SWAP1 0000178f: PUSH2 0x1798 00001792: SWAP2 00001793: SWAP1 00001794: PUSH2 0x2744 00001797: JUMP 00001798: JUMPDEST 00001799: PUSH1 0x40 0000179b: MLOAD 0000179c: PUSH4 0x55189a3d 000017a1: PUSH1 0xe1 000017a3: SHL 000017a4: DUP2 000017a5: MSTORE 000017a6: PUSH1 0x04 000017a8: DUP2 000017a9: ADD 000017aa: DUP7 000017ab: SWAP1 000017ac: MSTORE 000017ad: PUSH1 0x01 000017af: PUSH1 0x01 000017b1: PUSH1 0xa0 000017b3: SHL 000017b4: SUB 000017b5: DUP6 000017b6: DUP2 000017b7: AND 000017b8: PUSH1 0x24 000017ba: DUP4 000017bb: ADD 000017bc: MSTORE 000017bd: SWAP2 000017be: SWAP3 000017bf: POP 000017c0: SWAP1 000017c1: DUP3 000017c2: AND 000017c3: SWAP1 000017c4: PUSH4 0xaa31347a 000017c9: SWAP1 000017ca: PUSH1 0x44 000017cc: ADD 000017cd: PUSH2 0x0d68 000017d0: JUMP 000017d1: JUMPDEST 000017d2: PUSH1 0x00 000017d4: DUP1 000017d5: PUSH1 0x01 000017d7: PUSH1 0x01 000017d9: PUSH1 0xa0 000017db: SHL 000017dc: SUB 000017dd: AND 000017de: PUSH1 0xcb 000017e0: PUSH1 0x00 000017e2: PUSH2 0x1820 000017e5: DUP7 000017e6: DUP7 000017e7: DUP1 000017e8: DUP1 000017e9: PUSH1 0x1f 000017eb: ADD 000017ec: PUSH1 0x20 000017ee: DUP1 000017ef: SWAP2 000017f0: DIV 000017f1: MUL 000017f2: PUSH1 0x20 000017f4: ADD 000017f5: PUSH1 0x40 000017f7: MLOAD 000017f8: SWAP1 000017f9: DUP2 000017fa: ADD 000017fb: PUSH1 0x40 000017fd: MSTORE 000017fe: DUP1 000017ff: SWAP4 00001800: SWAP3 00001801: SWAP2 00001802: SWAP1 00001803: DUP2 00001804: DUP2 00001805: MSTORE 00001806: PUSH1 0x20 00001808: ADD 00001809: DUP4 0000180a: DUP4 0000180b: DUP1 0000180c: DUP3 0000180d: DUP5 0000180e: CALLDATACOPY 0000180f: PUSH1 0x00 00001811: SWAP3 00001812: ADD 00001813: SWAP2 00001814: SWAP1 00001815: SWAP2 00001816: MSTORE 00001817: POP 00001818: PUSH2 0x1c45 0000181b: SWAP3 0000181c: POP 0000181d: POP 0000181e: POP 0000181f: JUMP 00001820: JUMPDEST 00001821: DUP2 00001822: MSTORE 00001823: PUSH1 0x20 00001825: DUP2 00001826: ADD 00001827: SWAP2 00001828: SWAP1 00001829: SWAP2 0000182a: MSTORE 0000182b: PUSH1 0x40 0000182d: ADD 0000182e: PUSH1 0x00 00001830: KECCAK256 00001831: SLOAD 00001832: PUSH1 0x01 00001834: PUSH1 0x01 00001836: PUSH1 0xa0 00001838: SHL 00001839: SUB 0000183a: AND 0000183b: EQ 0000183c: ISZERO 0000183d: SWAP4 0000183e: SWAP3 0000183f: POP 00001840: POP 00001841: POP 00001842: JUMP 00001843: JUMPDEST 00001844: PUSH1 0x00 00001846: SLOAD 00001847: PUSH2 0x0100 0000184a: SWAP1 0000184b: DIV 0000184c: PUSH1 0xff 0000184e: AND 0000184f: ISZERO 00001850: DUP1 00001851: DUP1 00001852: ISZERO 00001853: PUSH2 0x1863 00001856: JUMPI 00001857: POP 00001858: PUSH1 0x00 0000185a: SLOAD 0000185b: PUSH1 0x01 0000185d: PUSH1 0xff 0000185f: SWAP1 00001860: SWAP2 00001861: AND 00001862: LT 00001863: JUMPDEST 00001864: DUP1 00001865: PUSH2 0x187d 00001868: JUMPI 00001869: POP 0000186a: ADDRESS 0000186b: EXTCODESIZE 0000186c: ISZERO 0000186d: DUP1 0000186e: ISZERO 0000186f: PUSH2 0x187d 00001872: JUMPI 00001873: POP 00001874: PUSH1 0x00 00001876: SLOAD 00001877: PUSH1 0xff 00001879: AND 0000187a: PUSH1 0x01 0000187c: EQ 0000187d: JUMPDEST 0000187e: PUSH2 0x1899 00001881: JUMPI 00001882: PUSH1 0x40 00001884: MLOAD 00001885: PUSH3 0x461bcd 00001889: PUSH1 0xe5 0000188b: SHL 0000188c: DUP2 0000188d: MSTORE 0000188e: PUSH1 0x04 00001890: ADD 00001891: PUSH2 0x0776 00001894: SWAP1 00001895: PUSH2 0x2783 00001898: JUMP 00001899: JUMPDEST 0000189a: PUSH1 0x00 0000189c: DUP1 0000189d: SLOAD 0000189e: PUSH1 0xff 000018a0: NOT 000018a1: AND 000018a2: PUSH1 0x01 000018a4: OR 000018a5: SWAP1 000018a6: SSTORE 000018a7: DUP1 000018a8: ISZERO 000018a9: PUSH2 0x18bc 000018ac: JUMPI 000018ad: PUSH1 0x00 000018af: DUP1 000018b0: SLOAD 000018b1: PUSH2 0xff00 000018b4: NOT 000018b5: AND 000018b6: PUSH2 0x0100 000018b9: OR 000018ba: SWAP1 000018bb: SSTORE 000018bc: JUMPDEST 000018bd: PUSH2 0x18c6 000018c0: DUP5 000018c1: DUP4 000018c2: PUSH2 0x0db1 000018c5: JUMP 000018c6: JUMPDEST 000018c7: PUSH2 0x18de 000018ca: PUSH1 0x00 000018cc: DUP1 000018cd: MLOAD 000018ce: PUSH1 0x20 000018d0: PUSH2 0x2a15 000018d3: DUP4 000018d4: CODECOPY 000018d5: DUP2 000018d6: MLOAD 000018d7: SWAP2 000018d8: MSTORE 000018d9: DUP5 000018da: PUSH2 0x1e6f 000018dd: JUMP 000018de: JUMPDEST 000018df: PUSH3 0x0f4240 000018e3: PUSH1 0xce 000018e5: SSTORE 000018e6: PUSH1 0x03 000018e8: PUSH1 0xcf 000018ea: SSTORE 000018eb: PUSH1 0x02 000018ed: PUSH1 0xd0 000018ef: SSTORE 000018f0: DUP1 000018f1: ISZERO 000018f2: PUSH2 0x1701 000018f5: JUMPI 000018f6: PUSH1 0x00 000018f8: DUP1 000018f9: SLOAD 000018fa: PUSH2 0xff00 000018fd: NOT 000018fe: AND 000018ff: SWAP1 00001900: SSTORE 00001901: PUSH1 0x40 00001903: MLOAD 00001904: PUSH1 0x01 00001906: DUP2 00001907: MSTORE 00001908: PUSH32 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 00001929: SWAP1 0000192a: PUSH1 0x20 0000192c: ADD 0000192d: PUSH1 0x40 0000192f: MLOAD 00001930: DUP1 00001931: SWAP2 00001932: SUB 00001933: SWAP1 00001934: LOG1 00001935: POP 00001936: POP 00001937: POP 00001938: POP 00001939: JUMP 0000193a: JUMPDEST 0000193b: PUSH1 0x00 0000193d: SLOAD 0000193e: PUSH2 0x0100 00001941: SWAP1 00001942: DIV 00001943: PUSH1 0xff 00001945: AND 00001946: ISZERO 00001947: DUP1 00001948: DUP1 00001949: ISZERO 0000194a: PUSH2 0x195a 0000194d: JUMPI 0000194e: POP 0000194f: PUSH1 0x00 00001951: SLOAD 00001952: PUSH1 0x01 00001954: PUSH1 0xff 00001956: SWAP1 00001957: SWAP2 00001958: AND 00001959: LT 0000195a: JUMPDEST 0000195b: DUP1 0000195c: PUSH2 0x1974 0000195f: JUMPI 00001960: POP 00001961: ADDRESS 00001962: EXTCODESIZE 00001963: ISZERO 00001964: DUP1 00001965: ISZERO 00001966: PUSH2 0x1974 00001969: JUMPI 0000196a: POP 0000196b: PUSH1 0x00 0000196d: SLOAD 0000196e: PUSH1 0xff 00001970: AND 00001971: PUSH1 0x01 00001973: EQ 00001974: JUMPDEST 00001975: PUSH2 0x1990 00001978: JUMPI 00001979: PUSH1 0x40 0000197b: MLOAD 0000197c: PUSH3 0x461bcd 00001980: PUSH1 0xe5 00001982: SHL 00001983: DUP2 00001984: MSTORE 00001985: PUSH1 0x04 00001987: ADD 00001988: PUSH2 0x0776 0000198b: SWAP1 0000198c: PUSH2 0x2783 0000198f: JUMP 00001990: JUMPDEST 00001991: PUSH1 0x00 00001993: DUP1 00001994: SLOAD 00001995: PUSH1 0xff 00001997: NOT 00001998: AND 00001999: PUSH1 0x01 0000199b: OR 0000199c: SWAP1 0000199d: SSTORE 0000199e: DUP1 0000199f: ISZERO 000019a0: PUSH2 0x19b3 000019a3: JUMPI 000019a4: PUSH1 0x00 000019a6: DUP1 000019a7: SLOAD 000019a8: PUSH2 0xff00 000019ab: NOT 000019ac: AND 000019ad: PUSH2 0x0100 000019b0: OR 000019b1: SWAP1 000019b2: SSTORE 000019b3: JUMPDEST 000019b4: PUSH2 0x19bb 000019b7: PUSH2 0x1e79 000019ba: JUMP 000019bb: JUMPDEST 000019bc: PUSH2 0x19c6 000019bf: PUSH1 0x00 000019c1: CALLER 000019c2: PUSH2 0x1e6f 000019c5: JUMP 000019c6: JUMPDEST 000019c7: PUSH1 0xc9 000019c9: DUP1 000019ca: SLOAD 000019cb: PUSH1 0x01 000019cd: PUSH1 0x01 000019cf: PUSH1 0xa0 000019d1: SHL 000019d2: SUB 000019d3: NOT 000019d4: AND 000019d5: PUSH1 0x01 000019d7: PUSH1 0x01 000019d9: PUSH1 0xa0 000019db: SHL 000019dc: SUB 000019dd: DUP5 000019de: AND 000019df: OR 000019e0: SWAP1 000019e1: SSTORE 000019e2: DUP1 000019e3: ISZERO 000019e4: PUSH2 0x0c9e 000019e7: JUMPI 000019e8: PUSH1 0x00 000019ea: DUP1 000019eb: SLOAD 000019ec: PUSH2 0xff00 000019ef: NOT 000019f0: AND 000019f1: SWAP1 000019f2: SSTORE 000019f3: PUSH1 0x40 000019f5: MLOAD 000019f6: PUSH1 0x01 000019f8: DUP2 000019f9: MSTORE 000019fa: PUSH32 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 00001a1b: SWAP1 00001a1c: PUSH1 0x20 00001a1e: ADD 00001a1f: PUSH1 0x40 00001a21: MLOAD 00001a22: DUP1 00001a23: SWAP2 00001a24: SUB 00001a25: SWAP1 00001a26: LOG1 00001a27: POP 00001a28: POP 00001a29: JUMP 00001a2a: JUMPDEST 00001a2b: PUSH1 0x00 00001a2d: DUP2 00001a2e: DUP2 00001a2f: MSTORE 00001a30: PUSH1 0x97 00001a32: PUSH1 0x20 00001a34: MSTORE 00001a35: PUSH1 0x40 00001a37: DUP2 00001a38: KECCAK256 00001a39: PUSH2 0x0717 00001a3c: SWAP1 00001a3d: PUSH2 0x1ee6 00001a40: JUMP 00001a41: JUMPDEST 00001a42: PUSH1 0x00 00001a44: DUP3 00001a45: DUP2 00001a46: MSTORE 00001a47: PUSH1 0x65 00001a49: PUSH1 0x20 00001a4b: MSTORE 00001a4c: PUSH1 0x40 00001a4e: SWAP1 00001a4f: KECCAK256 00001a50: PUSH1 0x01 00001a52: ADD 00001a53: SLOAD 00001a54: PUSH2 0x1a5c 00001a57: DUP2 00001a58: PUSH2 0x1cbd 00001a5b: JUMP 00001a5c: JUMPDEST 00001a5d: PUSH2 0x0b0e 00001a60: DUP4 00001a61: DUP4 00001a62: PUSH2 0x1cec 00001a65: JUMP 00001a66: JUMPDEST 00001a67: PUSH1 0x00 00001a69: PUSH2 0x1aa7 00001a6c: DUP5 00001a6d: DUP5 00001a6e: DUP1 00001a6f: DUP1 00001a70: PUSH1 0x1f 00001a72: ADD 00001a73: PUSH1 0x20 00001a75: DUP1 00001a76: SWAP2 00001a77: DIV 00001a78: MUL 00001a79: PUSH1 0x20 00001a7b: ADD 00001a7c: PUSH1 0x40 00001a7e: MLOAD 00001a7f: SWAP1 00001a80: DUP2 00001a81: ADD 00001a82: PUSH1 0x40 00001a84: MSTORE 00001a85: DUP1 00001a86: SWAP4 00001a87: SWAP3 00001a88: SWAP2 00001a89: SWAP1 00001a8a: DUP2 00001a8b: DUP2 00001a8c: MSTORE 00001a8d: PUSH1 0x20 00001a8f: ADD 00001a90: DUP4 00001a91: DUP4 00001a92: DUP1 00001a93: DUP3 00001a94: DUP5 00001a95: CALLDATACOPY 00001a96: PUSH1 0x00 00001a98: SWAP3 00001a99: ADD 00001a9a: SWAP2 00001a9b: SWAP1 00001a9c: SWAP2 00001a9d: MSTORE 00001a9e: POP 00001a9f: PUSH2 0x1c45 00001aa2: SWAP3 00001aa3: POP 00001aa4: POP 00001aa5: POP 00001aa6: JUMP 00001aa7: JUMPDEST 00001aa8: SWAP1 00001aa9: POP 00001aaa: PUSH2 0x1ab4 00001aad: DUP2 00001aae: DUP4 00001aaf: CALLVALUE 00001ab0: PUSH2 0x1c75 00001ab3: JUMP 00001ab4: JUMPDEST 00001ab5: PUSH2 0x1b00 00001ab8: JUMPI 00001ab9: PUSH1 0x40 00001abb: MLOAD 00001abc: PUSH3 0x461bcd 00001ac0: PUSH1 0xe5 00001ac2: SHL 00001ac3: DUP2 00001ac4: MSTORE 00001ac5: PUSH1 0x20 00001ac7: PUSH1 0x04 00001ac9: DUP3 00001aca: ADD 00001acb: MSTORE 00001acc: PUSH1 0x1e 00001ace: PUSH1 0x24 00001ad0: DUP3 00001ad1: ADD 00001ad2: MSTORE 00001ad3: PUSH32 0x4e6f7420656e6f7567682045544820666f72207472616e73616374696f6e0000 00001af4: PUSH1 0x44 00001af6: DUP3 00001af7: ADD 00001af8: MSTORE 00001af9: PUSH1 0x64 00001afb: ADD 00001afc: PUSH2 0x0776 00001aff: JUMP 00001b00: JUMPDEST 00001b01: PUSH1 0x01 00001b03: PUSH1 0x01 00001b05: PUSH1 0xa0 00001b07: SHL 00001b08: SUB 00001b09: DUP3 00001b0a: AND 00001b0b: PUSH1 0x00 00001b0d: SWAP1 00001b0e: DUP2 00001b0f: MSTORE 00001b10: PUSH1 0xcc 00001b12: PUSH1 0x20 00001b14: SWAP1 00001b15: DUP2 00001b16: MSTORE 00001b17: PUSH1 0x40 00001b19: DUP1 00001b1a: DUP4 00001b1b: KECCAK256 00001b1c: DUP5 00001b1d: DUP5 00001b1e: MSTORE 00001b1f: SWAP1 00001b20: SWAP2 00001b21: MSTORE 00001b22: SWAP1 00001b23: KECCAK256 00001b24: SLOAD 00001b25: PUSH2 0x1b2f 00001b28: SWAP1 00001b29: CALLVALUE 00001b2a: SWAP1 00001b2b: PUSH2 0x28b6 00001b2e: JUMP 00001b2f: JUMPDEST 00001b30: PUSH1 0x01 00001b32: PUSH1 0x01 00001b34: PUSH1 0xa0 00001b36: SHL 00001b37: SUB 00001b38: DUP4 00001b39: AND 00001b3a: PUSH1 0x00 00001b3c: DUP2 00001b3d: DUP2 00001b3e: MSTORE 00001b3f: PUSH1 0xcc 00001b41: PUSH1 0x20 00001b43: SWAP1 00001b44: DUP2 00001b45: MSTORE 00001b46: PUSH1 0x40 00001b48: DUP1 00001b49: DUP4 00001b4a: KECCAK256 00001b4b: DUP7 00001b4c: DUP5 00001b4d: MSTORE 00001b4e: DUP3 00001b4f: MSTORE 00001b50: DUP1 00001b51: DUP4 00001b52: KECCAK256 00001b53: SWAP5 00001b54: SWAP1 00001b55: SWAP5 00001b56: SSTORE 00001b57: SWAP2 00001b58: DUP2 00001b59: MSTORE 00001b5a: PUSH1 0xcd 00001b5c: DUP3 00001b5d: MSTORE 00001b5e: DUP3 00001b5f: DUP2 00001b60: KECCAK256 00001b61: DUP5 00001b62: DUP3 00001b63: MSTORE 00001b64: SWAP1 00001b65: SWAP2 00001b66: MSTORE 00001b67: KECCAK256 00001b68: SLOAD 00001b69: PUSH1 0xff 00001b6b: AND 00001b6c: PUSH2 0x1701 00001b6f: JUMPI 00001b70: PUSH1 0x01 00001b72: PUSH1 0x01 00001b74: PUSH1 0xa0 00001b76: SHL 00001b77: SUB 00001b78: DUP1 00001b79: DUP4 00001b7a: AND 00001b7b: PUSH1 0x00 00001b7d: SWAP1 00001b7e: DUP2 00001b7f: MSTORE 00001b80: PUSH1 0xcd 00001b82: PUSH1 0x20 00001b84: SWAP1 00001b85: DUP2 00001b86: MSTORE 00001b87: PUSH1 0x40 00001b89: DUP1 00001b8a: DUP4 00001b8b: KECCAK256 00001b8c: DUP6 00001b8d: DUP5 00001b8e: MSTORE 00001b8f: SWAP1 00001b90: SWAP2 00001b91: MSTORE 00001b92: SWAP1 00001b93: KECCAK256 00001b94: DUP1 00001b95: SLOAD 00001b96: PUSH1 0xff 00001b98: NOT 00001b99: AND 00001b9a: PUSH1 0x01 00001b9c: OR 00001b9d: SWAP1 00001b9e: SSTORE 00001b9f: PUSH1 0xca 00001ba1: SLOAD 00001ba2: AND 00001ba3: PUSH4 0x94489202 00001ba8: DUP3 00001ba9: PUSH2 0x1bb1 00001bac: DUP2 00001bad: PUSH2 0x13b5 00001bb0: JUMP 00001bb1: JUMPDEST 00001bb2: PUSH2 0x1bba 00001bb5: DUP7 00001bb6: PUSH2 0x1ef0 00001bb9: JUMP 00001bba: JUMPDEST 00001bbb: PUSH1 0x40 00001bbd: MLOAD 00001bbe: DUP5 00001bbf: PUSH4 0xffffffff 00001bc4: AND 00001bc5: PUSH1 0xe0 00001bc7: SHL 00001bc8: DUP2 00001bc9: MSTORE 00001bca: PUSH1 0x04 00001bcc: ADD 00001bcd: PUSH2 0x1bd8 00001bd0: SWAP4 00001bd1: SWAP3 00001bd2: SWAP2 00001bd3: SWAP1 00001bd4: PUSH2 0x2861 00001bd7: JUMP 00001bd8: JUMPDEST 00001bd9: PUSH1 0x00 00001bdb: PUSH1 0x40 00001bdd: MLOAD 00001bde: DUP1 00001bdf: DUP4 00001be0: SUB 00001be1: DUP2 00001be2: PUSH1 0x00 00001be4: DUP8 00001be5: DUP1 00001be6: EXTCODESIZE 00001be7: ISZERO 00001be8: DUP1 00001be9: ISZERO 00001bea: PUSH2 0x1bf2 00001bed: JUMPI 00001bee: PUSH1 0x00 00001bf0: DUP1 00001bf1: REVERT 00001bf2: JUMPDEST 00001bf3: POP 00001bf4: GAS 00001bf5: CALL 00001bf6: ISZERO 00001bf7: DUP1 00001bf8: ISZERO 00001bf9: PUSH2 0x1c06 00001bfc: JUMPI 00001bfd: RETURNDATASIZE 00001bfe: PUSH1 0x00 00001c00: DUP1 00001c01: RETURNDATACOPY 00001c02: RETURNDATASIZE 00001c03: PUSH1 0x00 00001c05: REVERT 00001c06: JUMPDEST 00001c07: POP 00001c08: POP 00001c09: POP 00001c0a: POP 00001c0b: POP 00001c0c: POP 00001c0d: POP 00001c0e: POP 00001c0f: JUMP 00001c10: JUMPDEST 00001c11: PUSH1 0x00 00001c13: PUSH1 0x01 00001c15: PUSH1 0x01 00001c17: PUSH1 0xe0 00001c19: SHL 00001c1a: SUB 00001c1b: NOT 00001c1c: DUP3 00001c1d: AND 00001c1e: PUSH4 0x7965db0b 00001c23: PUSH1 0xe0 00001c25: SHL 00001c26: EQ 00001c27: DUP1 00001c28: PUSH2 0x0717 00001c2b: JUMPI 00001c2c: POP 00001c2d: PUSH4 0x01ffc9a7 00001c32: PUSH1 0xe0 00001c34: SHL 00001c35: PUSH1 0x01 00001c37: PUSH1 0x01 00001c39: PUSH1 0xe0 00001c3b: SHL 00001c3c: SUB 00001c3d: NOT 00001c3e: DUP4 00001c3f: AND 00001c40: EQ 00001c41: PUSH2 0x0717 00001c44: JUMP 00001c45: JUMPDEST 00001c46: PUSH1 0x00 00001c48: DUP2 00001c49: PUSH1 0x40 00001c4b: MLOAD 00001c4c: PUSH1 0x20 00001c4e: ADD 00001c4f: PUSH2 0x1c58 00001c52: SWAP2 00001c53: SWAP1 00001c54: PUSH2 0x28c9 00001c57: JUMP 00001c58: JUMPDEST 00001c59: PUSH1 0x40 00001c5b: MLOAD 00001c5c: PUSH1 0x20 00001c5e: DUP2 00001c5f: DUP4 00001c60: SUB 00001c61: SUB 00001c62: DUP2 00001c63: MSTORE 00001c64: SWAP1 00001c65: PUSH1 0x40 00001c67: MSTORE 00001c68: DUP1 00001c69: MLOAD 00001c6a: SWAP1 00001c6b: PUSH1 0x20 00001c6d: ADD 00001c6e: KECCAK256 00001c6f: SWAP1 00001c70: POP 00001c71: SWAP2 00001c72: SWAP1 00001c73: POP 00001c74: JUMP 00001c75: JUMPDEST 00001c76: PUSH1 0x00 00001c78: GASPRICE 00001c79: PUSH1 0xce 00001c7b: SLOAD 00001c7c: PUSH2 0x1c85 00001c7f: SWAP2 00001c80: SWAP1 00001c81: PUSH2 0x27e7 00001c84: JUMP 00001c85: JUMPDEST 00001c86: PUSH1 0x01 00001c88: PUSH1 0x01 00001c8a: PUSH1 0xa0 00001c8c: SHL 00001c8d: SUB 00001c8e: DUP5 00001c8f: AND 00001c90: PUSH1 0x00 00001c92: SWAP1 00001c93: DUP2 00001c94: MSTORE 00001c95: PUSH1 0xcc 00001c97: PUSH1 0x20 00001c99: SWAP1 00001c9a: DUP2 00001c9b: MSTORE 00001c9c: PUSH1 0x40 00001c9e: DUP1 00001c9f: DUP4 00001ca0: KECCAK256 00001ca1: DUP9 00001ca2: DUP5 00001ca3: MSTORE 00001ca4: SWAP1 00001ca5: SWAP2 00001ca6: MSTORE 00001ca7: SWAP1 00001ca8: KECCAK256 00001ca9: SLOAD 00001caa: PUSH2 0x1cb3 00001cad: SWAP1 00001cae: DUP5 00001caf: PUSH2 0x28b6 00001cb2: JUMP 00001cb3: JUMPDEST 00001cb4: LT 00001cb5: ISZERO 00001cb6: SWAP5 00001cb7: SWAP4 00001cb8: POP 00001cb9: POP 00001cba: POP 00001cbb: POP 00001cbc: JUMP 00001cbd: JUMPDEST 00001cbe: PUSH2 0x1cc7 00001cc1: DUP2 00001cc2: CALLER 00001cc3: PUSH2 0x1efd 00001cc6: JUMP 00001cc7: JUMPDEST 00001cc8: POP 00001cc9: JUMP 00001cca: JUMPDEST 00001ccb: PUSH2 0x1cd4 00001cce: DUP3 00001ccf: DUP3 00001cd0: PUSH2 0x1f56 00001cd3: JUMP 00001cd4: JUMPDEST 00001cd5: PUSH1 0x00 00001cd7: DUP3 00001cd8: DUP2 00001cd9: MSTORE 00001cda: PUSH1 0x97 00001cdc: PUSH1 0x20 00001cde: MSTORE 00001cdf: PUSH1 0x40 00001ce1: SWAP1 00001ce2: KECCAK256 00001ce3: PUSH2 0x0b0e 00001ce6: SWAP1 00001ce7: DUP3 00001ce8: PUSH2 0x1fdc 00001ceb: JUMP 00001cec: JUMPDEST 00001ced: PUSH2 0x1cf6 00001cf0: DUP3 00001cf1: DUP3 00001cf2: PUSH2 0x1ff1 00001cf5: JUMP 00001cf6: JUMPDEST 00001cf7: PUSH1 0x00 00001cf9: DUP3 00001cfa: DUP2 00001cfb: MSTORE 00001cfc: PUSH1 0x97 00001cfe: PUSH1 0x20 00001d00: MSTORE 00001d01: PUSH1 0x40 00001d03: SWAP1 00001d04: KECCAK256 00001d05: PUSH2 0x0b0e 00001d08: SWAP1 00001d09: DUP3 00001d0a: PUSH2 0x2058 00001d0d: JUMP 00001d0e: JUMPDEST 00001d0f: PUSH1 0x60 00001d11: PUSH2 0x0717 00001d14: DUP3 00001d15: PUSH1 0x00 00001d17: PUSH2 0x206d 00001d1a: JUMP 00001d1b: JUMPDEST 00001d1c: DUP1 00001d1d: SELFBALANCE 00001d1e: LT 00001d1f: ISZERO 00001d20: PUSH2 0x1d6b 00001d23: JUMPI 00001d24: PUSH1 0x40 00001d26: MLOAD 00001d27: PUSH3 0x461bcd 00001d2b: PUSH1 0xe5 00001d2d: SHL 00001d2e: DUP2 00001d2f: MSTORE 00001d30: PUSH1 0x20 00001d32: PUSH1 0x04 00001d34: DUP3 00001d35: ADD 00001d36: MSTORE 00001d37: PUSH1 0x1d 00001d39: PUSH1 0x24 00001d3b: DUP3 00001d3c: ADD 00001d3d: MSTORE 00001d3e: PUSH32 0x416464726573733a20696e73756666696369656e742062616c616e6365000000 00001d5f: PUSH1 0x44 00001d61: DUP3 00001d62: ADD 00001d63: MSTORE 00001d64: PUSH1 0x64 00001d66: ADD 00001d67: PUSH2 0x0776 00001d6a: JUMP 00001d6b: JUMPDEST 00001d6c: PUSH1 0x00 00001d6e: DUP3 00001d6f: PUSH1 0x01 00001d71: PUSH1 0x01 00001d73: PUSH1 0xa0 00001d75: SHL 00001d76: SUB 00001d77: AND 00001d78: DUP3 00001d79: PUSH1 0x40 00001d7b: MLOAD 00001d7c: PUSH1 0x00 00001d7e: PUSH1 0x40 00001d80: MLOAD 00001d81: DUP1 00001d82: DUP4 00001d83: SUB 00001d84: DUP2 00001d85: DUP6 00001d86: DUP8 00001d87: GAS 00001d88: CALL 00001d89: SWAP3 00001d8a: POP 00001d8b: POP 00001d8c: POP 00001d8d: RETURNDATASIZE 00001d8e: DUP1 00001d8f: PUSH1 0x00 00001d91: DUP2 00001d92: EQ 00001d93: PUSH2 0x1db8 00001d96: JUMPI 00001d97: PUSH1 0x40 00001d99: MLOAD 00001d9a: SWAP2 00001d9b: POP 00001d9c: PUSH1 0x1f 00001d9e: NOT 00001d9f: PUSH1 0x3f 00001da1: RETURNDATASIZE 00001da2: ADD 00001da3: AND 00001da4: DUP3 00001da5: ADD 00001da6: PUSH1 0x40 00001da8: MSTORE 00001da9: RETURNDATASIZE 00001daa: DUP3 00001dab: MSTORE 00001dac: RETURNDATASIZE 00001dad: PUSH1 0x00 00001daf: PUSH1 0x20 00001db1: DUP5 00001db2: ADD 00001db3: RETURNDATACOPY 00001db4: PUSH2 0x1dbd 00001db7: JUMP 00001db8: JUMPDEST 00001db9: PUSH1 0x60 00001dbb: SWAP2 00001dbc: POP 00001dbd: JUMPDEST 00001dbe: POP 00001dbf: POP 00001dc0: SWAP1 00001dc1: POP 00001dc2: DUP1 00001dc3: PUSH2 0x0b0e 00001dc6: JUMPI 00001dc7: PUSH1 0x40 00001dc9: MLOAD 00001dca: PUSH3 0x461bcd 00001dce: PUSH1 0xe5 00001dd0: SHL 00001dd1: DUP2 00001dd2: MSTORE 00001dd3: PUSH1 0x20 00001dd5: PUSH1 0x04 00001dd7: DUP3 00001dd8: ADD 00001dd9: MSTORE 00001dda: PUSH1 0x3a 00001ddc: PUSH1 0x24 00001dde: DUP3 00001ddf: ADD 00001de0: MSTORE 00001de1: PUSH32 0x416464726573733a20756e61626c6520746f2073656e642076616c75652c2072 00001e02: PUSH1 0x44 00001e04: DUP3 00001e05: ADD 00001e06: MSTORE 00001e07: PUSH32 0x6563697069656e74206d61792068617665207265766572746564000000000000 00001e28: PUSH1 0x64 00001e2a: DUP3 00001e2b: ADD 00001e2c: MSTORE 00001e2d: PUSH1 0x84 00001e2f: ADD 00001e30: PUSH2 0x0776 00001e33: JUMP 00001e34: JUMPDEST 00001e35: PUSH1 0x00 00001e37: PUSH1 0xd0 00001e39: SLOAD 00001e3a: PUSH1 0xcf 00001e3c: SLOAD 00001e3d: GASPRICE 00001e3e: PUSH1 0xce 00001e40: SLOAD 00001e41: PUSH2 0x1e4a 00001e44: SWAP2 00001e45: SWAP1 00001e46: PUSH2 0x27e7 00001e49: JUMP 00001e4a: JUMPDEST 00001e4b: PUSH2 0x1e54 00001e4e: SWAP2 00001e4f: SWAP1 00001e50: PUSH2 0x27e7 00001e53: JUMP 00001e54: JUMPDEST 00001e55: PUSH2 0x1e5e 00001e58: SWAP2 00001e59: SWAP1 00001e5a: PUSH2 0x2894 00001e5d: JUMP 00001e5e: JUMPDEST 00001e5f: SWAP1 00001e60: POP 00001e61: SWAP1 00001e62: JUMP 00001e63: JUMPDEST 00001e64: PUSH1 0x00 00001e66: PUSH2 0x0ae2 00001e69: DUP4 00001e6a: DUP4 00001e6b: PUSH2 0x20c6 00001e6e: JUMP 00001e6f: JUMPDEST 00001e70: PUSH2 0x0c9e 00001e73: DUP3 00001e74: DUP3 00001e75: PUSH2 0x1cca 00001e78: JUMP 00001e79: JUMPDEST 00001e7a: PUSH1 0x00 00001e7c: SLOAD 00001e7d: PUSH2 0x0100 00001e80: SWAP1 00001e81: DIV 00001e82: PUSH1 0xff 00001e84: AND 00001e85: PUSH2 0x1ee4 00001e88: JUMPI 00001e89: PUSH1 0x40 00001e8b: MLOAD 00001e8c: PUSH3 0x461bcd 00001e90: PUSH1 0xe5 00001e92: SHL 00001e93: DUP2 00001e94: MSTORE 00001e95: PUSH1 0x20 00001e97: PUSH1 0x04 00001e99: DUP3 00001e9a: ADD 00001e9b: MSTORE 00001e9c: PUSH1 0x2b 00001e9e: PUSH1 0x24 00001ea0: DUP3 00001ea1: ADD 00001ea2: MSTORE 00001ea3: PUSH32 0x496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069 00001ec4: PUSH1 0x44 00001ec6: DUP3 00001ec7: ADD 00001ec8: MSTORE 00001ec9: PUSH11 0x6e697469616c697a696e67 00001ed5: PUSH1 0xa8 00001ed7: SHL 00001ed8: PUSH1 0x64 00001eda: DUP3 00001edb: ADD 00001edc: MSTORE 00001edd: PUSH1 0x84 00001edf: ADD 00001ee0: PUSH2 0x0776 00001ee3: JUMP 00001ee4: JUMPDEST 00001ee5: JUMP 00001ee6: JUMPDEST 00001ee7: PUSH1 0x00 00001ee9: PUSH2 0x0717 00001eec: DUP3 00001eed: SLOAD 00001eee: SWAP1 00001eef: JUMP 00001ef0: JUMPDEST 00001ef1: PUSH1 0x60 00001ef3: PUSH2 0x0717 00001ef6: DUP3 00001ef7: PUSH1 0x01 00001ef9: PUSH2 0x206d 00001efc: JUMP 00001efd: JUMPDEST 00001efe: PUSH2 0x1f07 00001f01: DUP3 00001f02: DUP3 00001f03: PUSH2 0x1459 00001f06: JUMP 00001f07: JUMPDEST 00001f08: PUSH2 0x0c9e 00001f0b: JUMPI 00001f0c: PUSH2 0x1f14 00001f0f: DUP2 00001f10: PUSH2 0x20f0 00001f13: JUMP 00001f14: JUMPDEST 00001f15: PUSH2 0x1f1f 00001f18: DUP4 00001f19: PUSH1 0x20 00001f1b: PUSH2 0x2102 00001f1e: JUMP 00001f1f: JUMPDEST 00001f20: PUSH1 0x40 00001f22: MLOAD 00001f23: PUSH1 0x20 00001f25: ADD 00001f26: PUSH2 0x1f30 00001f29: SWAP3 00001f2a: SWAP2 00001f2b: SWAP1 00001f2c: PUSH2 0x28e5 00001f2f: JUMP 00001f30: JUMPDEST 00001f31: PUSH1 0x40 00001f33: DUP1 00001f34: MLOAD 00001f35: PUSH1 0x1f 00001f37: NOT 00001f38: DUP2 00001f39: DUP5 00001f3a: SUB 00001f3b: ADD 00001f3c: DUP2 00001f3d: MSTORE 00001f3e: SWAP1 00001f3f: DUP3 00001f40: SWAP1 00001f41: MSTORE 00001f42: PUSH3 0x461bcd 00001f46: PUSH1 0xe5 00001f48: SHL 00001f49: DUP3 00001f4a: MSTORE 00001f4b: PUSH2 0x0776 00001f4e: SWAP2 00001f4f: PUSH1 0x04 00001f51: ADD 00001f52: PUSH2 0x295a 00001f55: JUMP 00001f56: JUMPDEST 00001f57: PUSH2 0x1f60 00001f5a: DUP3 00001f5b: DUP3 00001f5c: PUSH2 0x1459 00001f5f: JUMP 00001f60: JUMPDEST 00001f61: PUSH2 0x0c9e 00001f64: JUMPI 00001f65: PUSH1 0x00 00001f67: DUP3 00001f68: DUP2 00001f69: MSTORE 00001f6a: PUSH1 0x65 00001f6c: PUSH1 0x20 00001f6e: SWAP1 00001f6f: DUP2 00001f70: MSTORE 00001f71: PUSH1 0x40 00001f73: DUP1 00001f74: DUP4 00001f75: KECCAK256 00001f76: PUSH1 0x01 00001f78: PUSH1 0x01 00001f7a: PUSH1 0xa0 00001f7c: SHL 00001f7d: SUB 00001f7e: DUP6 00001f7f: AND 00001f80: DUP5 00001f81: MSTORE 00001f82: SWAP1 00001f83: SWAP2 00001f84: MSTORE 00001f85: SWAP1 00001f86: KECCAK256 00001f87: DUP1 00001f88: SLOAD 00001f89: PUSH1 0xff 00001f8b: NOT 00001f8c: AND 00001f8d: PUSH1 0x01 00001f8f: OR 00001f90: SWAP1 00001f91: SSTORE 00001f92: PUSH2 0x1f98 00001f95: CALLER 00001f96: SWAP1 00001f97: JUMP 00001f98: JUMPDEST 00001f99: PUSH1 0x01 00001f9b: PUSH1 0x01 00001f9d: PUSH1 0xa0 00001f9f: SHL 00001fa0: SUB 00001fa1: AND 00001fa2: DUP2 00001fa3: PUSH1 0x01 00001fa5: PUSH1 0x01 00001fa7: PUSH1 0xa0 00001fa9: SHL 00001faa: SUB 00001fab: AND 00001fac: DUP4 00001fad: PUSH32 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d 00001fce: PUSH1 0x40 00001fd0: MLOAD 00001fd1: PUSH1 0x40 00001fd3: MLOAD 00001fd4: DUP1 00001fd5: SWAP2 00001fd6: SUB 00001fd7: SWAP1 00001fd8: LOG4 00001fd9: POP 00001fda: POP 00001fdb: JUMP 00001fdc: JUMPDEST 00001fdd: PUSH1 0x00 00001fdf: PUSH2 0x0ae2 00001fe2: DUP4 00001fe3: PUSH1 0x01 00001fe5: PUSH1 0x01 00001fe7: PUSH1 0xa0 00001fe9: SHL 00001fea: SUB 00001feb: DUP5 00001fec: AND 00001fed: PUSH2 0x229e 00001ff0: JUMP 00001ff1: JUMPDEST 00001ff2: PUSH2 0x1ffb 00001ff5: DUP3 00001ff6: DUP3 00001ff7: PUSH2 0x1459 00001ffa: JUMP 00001ffb: JUMPDEST 00001ffc: ISZERO 00001ffd: PUSH2 0x0c9e 00002000: JUMPI 00002001: PUSH1 0x00 00002003: DUP3 00002004: DUP2 00002005: MSTORE 00002006: PUSH1 0x65 00002008: PUSH1 0x20 0000200a: SWAP1 0000200b: DUP2 0000200c: MSTORE 0000200d: PUSH1 0x40 0000200f: DUP1 00002010: DUP4 00002011: KECCAK256 00002012: PUSH1 0x01 00002014: PUSH1 0x01 00002016: PUSH1 0xa0 00002018: SHL 00002019: SUB 0000201a: DUP6 0000201b: AND 0000201c: DUP1 0000201d: DUP6 0000201e: MSTORE 0000201f: SWAP3 00002020: MSTORE 00002021: DUP1 00002022: DUP4 00002023: KECCAK256 00002024: DUP1 00002025: SLOAD 00002026: PUSH1 0xff 00002028: NOT 00002029: AND 0000202a: SWAP1 0000202b: SSTORE 0000202c: MLOAD 0000202d: CALLER 0000202e: SWAP3 0000202f: DUP6 00002030: SWAP2 00002031: PUSH32 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b 00002052: SWAP2 00002053: SWAP1 00002054: LOG4 00002055: POP 00002056: POP 00002057: JUMP 00002058: JUMPDEST 00002059: PUSH1 0x00 0000205b: PUSH2 0x0ae2 0000205e: DUP4 0000205f: PUSH1 0x01 00002061: PUSH1 0x01 00002063: PUSH1 0xa0 00002065: SHL 00002066: SUB 00002067: DUP5 00002068: AND 00002069: PUSH2 0x22ed 0000206c: JUMP 0000206d: JUMPDEST 0000206e: PUSH1 0x40 00002070: DUP1 00002071: MLOAD 00002072: PUSH1 0x80 00002074: DUP2 00002075: ADD 00002076: DUP3 00002077: MSTORE 00002078: PUSH1 0x07 0000207a: PUSH1 0x60 0000207c: DUP1 0000207d: DUP4 0000207e: ADD 0000207f: SWAP2 00002080: DUP3 00002081: MSTORE 00002082: SWAP1 00002083: DUP3 00002084: MSTORE 00002085: PUSH1 0x01 00002087: PUSH1 0x01 00002089: PUSH1 0xa0 0000208b: SHL 0000208c: SUB 0000208d: DUP6 0000208e: AND 0000208f: PUSH1 0x20 00002091: DUP1 00002092: DUP5 00002093: ADD 00002094: SWAP2 00002095: SWAP1 00002096: SWAP2 00002097: MSTORE 00002098: DUP5 00002099: ISZERO 0000209a: ISZERO 0000209b: DUP4 0000209c: DUP6 0000209d: ADD 0000209e: MSTORE 0000209f: SWAP3 000020a0: MLOAD 000020a1: SWAP1 000020a2: SWAP3 000020a3: PUSH2 0x20ae 000020a6: SWAP2 000020a7: DUP4 000020a8: SWAP2 000020a9: ADD 000020aa: PUSH2 0x296d 000020ad: JUMP 000020ae: JUMPDEST 000020af: PUSH1 0x40 000020b1: MLOAD 000020b2: PUSH1 0x20 000020b4: DUP2 000020b5: DUP4 000020b6: SUB 000020b7: SUB 000020b8: DUP2 000020b9: MSTORE 000020ba: SWAP1 000020bb: PUSH1 0x40 000020bd: MSTORE 000020be: SWAP2 000020bf: POP 000020c0: POP 000020c1: SWAP3 000020c2: SWAP2 000020c3: POP 000020c4: POP 000020c5: JUMP 000020c6: JUMPDEST 000020c7: PUSH1 0x00 000020c9: DUP3 000020ca: PUSH1 0x00 000020cc: ADD 000020cd: DUP3 000020ce: DUP2 000020cf: SLOAD 000020d0: DUP2 000020d1: LT 000020d2: PUSH2 0x20dd 000020d5: JUMPI 000020d6: PUSH2 0x20dd 000020d9: PUSH2 0x29bb 000020dc: JUMP 000020dd: JUMPDEST 000020de: SWAP1 000020df: PUSH1 0x00 000020e1: MSTORE 000020e2: PUSH1 0x20 000020e4: PUSH1 0x00 000020e6: KECCAK256 000020e7: ADD 000020e8: SLOAD 000020e9: SWAP1 000020ea: POP 000020eb: SWAP3 000020ec: SWAP2 000020ed: POP 000020ee: POP 000020ef: JUMP 000020f0: JUMPDEST 000020f1: PUSH1 0x60 000020f3: PUSH2 0x0717 000020f6: PUSH1 0x01 000020f8: PUSH1 0x01 000020fa: PUSH1 0xa0 000020fc: SHL 000020fd: SUB 000020fe: DUP4 000020ff: AND 00002100: PUSH1 0x14 00002102: JUMPDEST 00002103: PUSH1 0x60 00002105: PUSH1 0x00 00002107: PUSH2 0x2111 0000210a: DUP4 0000210b: PUSH1 0x02 0000210d: PUSH2 0x27e7 00002110: JUMP 00002111: JUMPDEST 00002112: PUSH2 0x211c 00002115: SWAP1 00002116: PUSH1 0x02 00002118: PUSH2 0x28b6 0000211b: JUMP 0000211c: JUMPDEST 0000211d: PUSH8 0xffffffffffffffff 00002126: DUP2 00002127: GT 00002128: ISZERO 00002129: PUSH2 0x2134 0000212c: JUMPI 0000212d: PUSH2 0x2134 00002130: PUSH2 0x29d1 00002133: JUMP 00002134: JUMPDEST 00002135: PUSH1 0x40 00002137: MLOAD 00002138: SWAP1 00002139: DUP1 0000213a: DUP3 0000213b: MSTORE 0000213c: DUP1 0000213d: PUSH1 0x1f 0000213f: ADD 00002140: PUSH1 0x1f 00002142: NOT 00002143: AND 00002144: PUSH1 0x20 00002146: ADD 00002147: DUP3 00002148: ADD 00002149: PUSH1 0x40 0000214b: MSTORE 0000214c: DUP1 0000214d: ISZERO 0000214e: PUSH2 0x215e 00002151: JUMPI 00002152: PUSH1 0x20 00002154: DUP3 00002155: ADD 00002156: DUP2 00002157: DUP1 00002158: CALLDATASIZE 00002159: DUP4 0000215a: CALLDATACOPY 0000215b: ADD 0000215c: SWAP1 0000215d: POP 0000215e: JUMPDEST 0000215f: POP 00002160: SWAP1 00002161: POP 00002162: PUSH1 0x03 00002164: PUSH1 0xfc 00002166: SHL 00002167: DUP2 00002168: PUSH1 0x00 0000216a: DUP2 0000216b: MLOAD 0000216c: DUP2 0000216d: LT 0000216e: PUSH2 0x2179 00002171: JUMPI 00002172: PUSH2 0x2179 00002175: PUSH2 0x29bb 00002178: JUMP 00002179: JUMPDEST 0000217a: PUSH1 0x20 0000217c: ADD 0000217d: ADD 0000217e: SWAP1 0000217f: PUSH1 0x01 00002181: PUSH1 0x01 00002183: PUSH1 0xf8 00002185: SHL 00002186: SUB 00002187: NOT 00002188: AND 00002189: SWAP1 0000218a: DUP2 0000218b: PUSH1 0x00 0000218d: BYTE 0000218e: SWAP1 0000218f: MSTORE8 00002190: POP 00002191: PUSH1 0x0f 00002193: PUSH1 0xfb 00002195: SHL 00002196: DUP2 00002197: PUSH1 0x01 00002199: DUP2 0000219a: MLOAD 0000219b: DUP2 0000219c: LT 0000219d: PUSH2 0x21a8 000021a0: JUMPI 000021a1: PUSH2 0x21a8 000021a4: PUSH2 0x29bb 000021a7: JUMP 000021a8: JUMPDEST 000021a9: PUSH1 0x20 000021ab: ADD 000021ac: ADD 000021ad: SWAP1 000021ae: PUSH1 0x01 000021b0: PUSH1 0x01 000021b2: PUSH1 0xf8 000021b4: SHL 000021b5: SUB 000021b6: NOT 000021b7: AND 000021b8: SWAP1 000021b9: DUP2 000021ba: PUSH1 0x00 000021bc: BYTE 000021bd: SWAP1 000021be: MSTORE8 000021bf: POP 000021c0: PUSH1 0x00 000021c2: PUSH2 0x21cc 000021c5: DUP5 000021c6: PUSH1 0x02 000021c8: PUSH2 0x27e7 000021cb: JUMP 000021cc: JUMPDEST 000021cd: PUSH2 0x21d7 000021d0: SWAP1 000021d1: PUSH1 0x01 000021d3: PUSH2 0x28b6 000021d6: JUMP 000021d7: JUMPDEST 000021d8: SWAP1 000021d9: POP 000021da: JUMPDEST 000021db: PUSH1 0x01 000021dd: DUP2 000021de: GT 000021df: ISZERO 000021e0: PUSH2 0x224f 000021e3: JUMPI 000021e4: PUSH16 0x181899199a1a9b1b9c1cb0b131b232b3 000021f5: PUSH1 0x81 000021f7: SHL 000021f8: DUP6 000021f9: PUSH1 0x0f 000021fb: AND 000021fc: PUSH1 0x10 000021fe: DUP2 000021ff: LT 00002200: PUSH2 0x220b 00002203: JUMPI 00002204: PUSH2 0x220b 00002207: PUSH2 0x29bb 0000220a: JUMP 0000220b: JUMPDEST 0000220c: BYTE 0000220d: PUSH1 0xf8 0000220f: SHL 00002210: DUP3 00002211: DUP3 00002212: DUP2 00002213: MLOAD 00002214: DUP2 00002215: LT 00002216: PUSH2 0x2221 00002219: JUMPI 0000221a: PUSH2 0x2221 0000221d: PUSH2 0x29bb 00002220: JUMP 00002221: JUMPDEST 00002222: PUSH1 0x20 00002224: ADD 00002225: ADD 00002226: SWAP1 00002227: PUSH1 0x01 00002229: PUSH1 0x01 0000222b: PUSH1 0xf8 0000222d: SHL 0000222e: SUB 0000222f: NOT 00002230: AND 00002231: SWAP1 00002232: DUP2 00002233: PUSH1 0x00 00002235: BYTE 00002236: SWAP1 00002237: MSTORE8 00002238: POP 00002239: PUSH1 0x04 0000223b: SWAP5 0000223c: SWAP1 0000223d: SWAP5 0000223e: SHR 0000223f: SWAP4 00002240: PUSH2 0x2248 00002243: DUP2 00002244: PUSH2 0x29e7 00002247: JUMP 00002248: JUMPDEST 00002249: SWAP1 0000224a: POP 0000224b: PUSH2 0x21da 0000224e: JUMP 0000224f: JUMPDEST 00002250: POP 00002251: DUP4 00002252: ISZERO 00002253: PUSH2 0x0ae2 00002256: JUMPI 00002257: PUSH1 0x40 00002259: MLOAD 0000225a: PUSH3 0x461bcd 0000225e: PUSH1 0xe5 00002260: SHL 00002261: DUP2 00002262: MSTORE 00002263: PUSH1 0x20 00002265: PUSH1 0x04 00002267: DUP3 00002268: ADD 00002269: DUP2 0000226a: SWAP1 0000226b: MSTORE 0000226c: PUSH1 0x24 0000226e: DUP3 0000226f: ADD 00002270: MSTORE 00002271: PUSH32 0x537472696e67733a20686578206c656e67746820696e73756666696369656e74 00002292: PUSH1 0x44 00002294: DUP3 00002295: ADD 00002296: MSTORE 00002297: PUSH1 0x64 00002299: ADD 0000229a: PUSH2 0x0776 0000229d: JUMP 0000229e: JUMPDEST 0000229f: PUSH1 0x00 000022a1: DUP2 000022a2: DUP2 000022a3: MSTORE 000022a4: PUSH1 0x01 000022a6: DUP4 000022a7: ADD 000022a8: PUSH1 0x20 000022aa: MSTORE 000022ab: PUSH1 0x40 000022ad: DUP2 000022ae: KECCAK256 000022af: SLOAD 000022b0: PUSH2 0x22e5 000022b3: JUMPI 000022b4: POP 000022b5: DUP2 000022b6: SLOAD 000022b7: PUSH1 0x01 000022b9: DUP2 000022ba: DUP2 000022bb: ADD 000022bc: DUP5 000022bd: SSTORE 000022be: PUSH1 0x00 000022c0: DUP5 000022c1: DUP2 000022c2: MSTORE 000022c3: PUSH1 0x20 000022c5: DUP1 000022c6: DUP3 000022c7: KECCAK256 000022c8: SWAP1 000022c9: SWAP4 000022ca: ADD 000022cb: DUP5 000022cc: SWAP1 000022cd: SSTORE 000022ce: DUP5 000022cf: SLOAD 000022d0: DUP5 000022d1: DUP3 000022d2: MSTORE 000022d3: DUP3 000022d4: DUP7 000022d5: ADD 000022d6: SWAP1 000022d7: SWAP4 000022d8: MSTORE 000022d9: PUSH1 0x40 000022db: SWAP1 000022dc: KECCAK256 000022dd: SWAP2 000022de: SWAP1 000022df: SWAP2 000022e0: SSTORE 000022e1: PUSH2 0x0717 000022e4: JUMP 000022e5: JUMPDEST 000022e6: POP 000022e7: PUSH1 0x00 000022e9: PUSH2 0x0717 000022ec: JUMP 000022ed: JUMPDEST 000022ee: PUSH1 0x00 000022f0: DUP2 000022f1: DUP2 000022f2: MSTORE 000022f3: PUSH1 0x01 000022f5: DUP4 000022f6: ADD 000022f7: PUSH1 0x20 000022f9: MSTORE 000022fa: PUSH1 0x40 000022fc: DUP2 000022fd: KECCAK256 000022fe: SLOAD 000022ff: DUP1 00002300: ISZERO 00002301: PUSH2 0x23d6 00002304: JUMPI 00002305: PUSH1 0x00 00002307: PUSH2 0x2311 0000230a: PUSH1 0x01 0000230c: DUP4 0000230d: PUSH2 0x27fe 00002310: JUMP 00002311: JUMPDEST 00002312: DUP6 00002313: SLOAD 00002314: SWAP1 00002315: SWAP2 00002316: POP 00002317: PUSH1 0x00 00002319: SWAP1 0000231a: PUSH2 0x2325 0000231d: SWAP1 0000231e: PUSH1 0x01 00002320: SWAP1 00002321: PUSH2 0x27fe 00002324: JUMP 00002325: JUMPDEST 00002326: SWAP1 00002327: POP 00002328: DUP2 00002329: DUP2 0000232a: EQ 0000232b: PUSH2 0x238a 0000232e: JUMPI 0000232f: PUSH1 0x00 00002331: DUP7 00002332: PUSH1 0x00 00002334: ADD 00002335: DUP3 00002336: DUP2 00002337: SLOAD 00002338: DUP2 00002339: LT 0000233a: PUSH2 0x2345 0000233d: JUMPI 0000233e: PUSH2 0x2345 00002341: PUSH2 0x29bb 00002344: JUMP 00002345: JUMPDEST 00002346: SWAP1 00002347: PUSH1 0x00 00002349: MSTORE 0000234a: PUSH1 0x20 0000234c: PUSH1 0x00 0000234e: KECCAK256 0000234f: ADD 00002350: SLOAD 00002351: SWAP1 00002352: POP 00002353: DUP1 00002354: DUP8 00002355: PUSH1 0x00 00002357: ADD 00002358: DUP5 00002359: DUP2 0000235a: SLOAD 0000235b: DUP2 0000235c: LT 0000235d: PUSH2 0x2368 00002360: JUMPI 00002361: PUSH2 0x2368 00002364: PUSH2 0x29bb 00002367: JUMP 00002368: JUMPDEST 00002369: PUSH1 0x00 0000236b: SWAP2 0000236c: DUP3 0000236d: MSTORE 0000236e: PUSH1 0x20 00002370: DUP1 00002371: DUP4 00002372: KECCAK256 00002373: SWAP1 00002374: SWAP2 00002375: ADD 00002376: SWAP3 00002377: SWAP1 00002378: SWAP3 00002379: SSTORE 0000237a: SWAP2 0000237b: DUP3 0000237c: MSTORE 0000237d: PUSH1 0x01 0000237f: DUP9 00002380: ADD 00002381: SWAP1 00002382: MSTORE 00002383: PUSH1 0x40 00002385: SWAP1 00002386: KECCAK256 00002387: DUP4 00002388: SWAP1 00002389: SSTORE 0000238a: JUMPDEST 0000238b: DUP6 0000238c: SLOAD 0000238d: DUP7 0000238e: SWAP1 0000238f: DUP1 00002390: PUSH2 0x239b 00002393: JUMPI 00002394: PUSH2 0x239b 00002397: PUSH2 0x29fe 0000239a: JUMP 0000239b: JUMPDEST 0000239c: PUSH1 0x01 0000239e: SWAP1 0000239f: SUB 000023a0: DUP2 000023a1: DUP2 000023a2: SWAP1 000023a3: PUSH1 0x00 000023a5: MSTORE 000023a6: PUSH1 0x20 000023a8: PUSH1 0x00 000023aa: KECCAK256 000023ab: ADD 000023ac: PUSH1 0x00 000023ae: SWAP1 000023af: SSTORE 000023b0: SWAP1 000023b1: SSTORE 000023b2: DUP6 000023b3: PUSH1 0x01 000023b5: ADD 000023b6: PUSH1 0x00 000023b8: DUP7 000023b9: DUP2 000023ba: MSTORE 000023bb: PUSH1 0x20 000023bd: ADD 000023be: SWAP1 000023bf: DUP2 000023c0: MSTORE 000023c1: PUSH1 0x20 000023c3: ADD 000023c4: PUSH1 0x00 000023c6: KECCAK256 000023c7: PUSH1 0x00 000023c9: SWAP1 000023ca: SSTORE 000023cb: PUSH1 0x01 000023cd: SWAP4 000023ce: POP 000023cf: POP 000023d0: POP 000023d1: POP 000023d2: PUSH2 0x0717 000023d5: JUMP 000023d6: JUMPDEST 000023d7: PUSH1 0x00 000023d9: SWAP2 000023da: POP 000023db: POP 000023dc: PUSH2 0x0717 000023df: JUMP 000023e0: JUMPDEST 000023e1: PUSH1 0x00 000023e3: PUSH1 0x20 000023e5: DUP3 000023e6: DUP5 000023e7: SUB 000023e8: SLT 000023e9: ISZERO 000023ea: PUSH2 0x23f2 000023ed: JUMPI 000023ee: PUSH1 0x00 000023f0: DUP1 000023f1: REVERT 000023f2: JUMPDEST 000023f3: DUP2 000023f4: CALLDATALOAD 000023f5: PUSH1 0x01 000023f7: PUSH1 0x01 000023f9: PUSH1 0xe0 000023fb: SHL 000023fc: SUB 000023fd: NOT 000023fe: DUP2 000023ff: AND 00002400: DUP2 00002401: EQ 00002402: PUSH2 0x0ae2 00002405: JUMPI 00002406: PUSH1 0x00 00002408: DUP1 00002409: REVERT 0000240a: JUMPDEST 0000240b: PUSH1 0x01 0000240d: PUSH1 0x01 0000240f: PUSH1 0xa0 00002411: SHL 00002412: SUB 00002413: DUP2 00002414: AND 00002415: DUP2 00002416: EQ 00002417: PUSH2 0x1cc7 0000241a: JUMPI 0000241b: PUSH1 0x00 0000241d: DUP1 0000241e: REVERT 0000241f: JUMPDEST 00002420: PUSH1 0x00 00002422: DUP1 00002423: PUSH1 0x00 00002425: PUSH1 0x60 00002427: DUP5 00002428: DUP7 00002429: SUB 0000242a: SLT 0000242b: ISZERO 0000242c: PUSH2 0x2434 0000242f: JUMPI 00002430: PUSH1 0x00 00002432: DUP1 00002433: REVERT 00002434: JUMPDEST 00002435: DUP4 00002436: CALLDATALOAD 00002437: SWAP3 00002438: POP 00002439: PUSH1 0x20 0000243b: DUP5 0000243c: ADD 0000243d: CALLDATALOAD 0000243e: PUSH2 0x2446 00002441: DUP2 00002442: PUSH2 0x240a 00002445: JUMP 00002446: JUMPDEST 00002447: SWAP3 00002448: SWAP6 00002449: SWAP3 0000244a: SWAP5 0000244b: POP 0000244c: POP 0000244d: POP 0000244e: PUSH1 0x40 00002450: SWAP2 00002451: SWAP1 00002452: SWAP2 00002453: ADD 00002454: CALLDATALOAD 00002455: SWAP1 00002456: JUMP 00002457: JUMPDEST 00002458: PUSH1 0x00 0000245a: DUP1 0000245b: DUP4 0000245c: PUSH1 0x1f 0000245e: DUP5 0000245f: ADD 00002460: SLT 00002461: PUSH2 0x2469 00002464: JUMPI 00002465: PUSH1 0x00 00002467: DUP1 00002468: REVERT 00002469: JUMPDEST 0000246a: POP 0000246b: DUP2 0000246c: CALLDATALOAD 0000246d: PUSH8 0xffffffffffffffff 00002476: DUP2 00002477: GT 00002478: ISZERO 00002479: PUSH2 0x2481 0000247c: JUMPI 0000247d: PUSH1 0x00 0000247f: DUP1 00002480: REVERT 00002481: JUMPDEST 00002482: PUSH1 0x20 00002484: DUP4 00002485: ADD 00002486: SWAP2 00002487: POP 00002488: DUP4 00002489: PUSH1 0x20 0000248b: DUP3 0000248c: DUP6 0000248d: ADD 0000248e: ADD 0000248f: GT 00002490: ISZERO 00002491: PUSH2 0x2499 00002494: JUMPI 00002495: PUSH1 0x00 00002497: DUP1 00002498: REVERT 00002499: JUMPDEST 0000249a: SWAP3 0000249b: POP 0000249c: SWAP3 0000249d: SWAP1 0000249e: POP 0000249f: JUMP 000024a0: JUMPDEST 000024a1: PUSH1 0x00 000024a3: DUP1 000024a4: PUSH1 0x00 000024a6: PUSH1 0x40 000024a8: DUP5 000024a9: DUP7 000024aa: SUB 000024ab: SLT 000024ac: ISZERO 000024ad: PUSH2 0x24b5 000024b0: JUMPI 000024b1: PUSH1 0x00 000024b3: DUP1 000024b4: REVERT 000024b5: JUMPDEST 000024b6: DUP4 000024b7: CALLDATALOAD 000024b8: PUSH2 0x24c0 000024bb: DUP2 000024bc: PUSH2 0x240a 000024bf: JUMP 000024c0: JUMPDEST 000024c1: SWAP3 000024c2: POP 000024c3: PUSH1 0x20 000024c5: DUP5 000024c6: ADD 000024c7: CALLDATALOAD 000024c8: PUSH8 0xffffffffffffffff 000024d1: DUP2 000024d2: GT 000024d3: ISZERO 000024d4: PUSH2 0x24dc 000024d7: JUMPI 000024d8: PUSH1 0x00 000024da: DUP1 000024db: REVERT 000024dc: JUMPDEST 000024dd: PUSH2 0x24e8 000024e0: DUP7 000024e1: DUP3 000024e2: DUP8 000024e3: ADD 000024e4: PUSH2 0x2457 000024e7: JUMP 000024e8: JUMPDEST 000024e9: SWAP5 000024ea: SWAP8 000024eb: SWAP1 000024ec: SWAP7 000024ed: POP 000024ee: SWAP4 000024ef: SWAP5 000024f0: POP 000024f1: POP 000024f2: POP 000024f3: POP 000024f4: JUMP 000024f5: JUMPDEST 000024f6: PUSH1 0x00 000024f8: DUP1 000024f9: PUSH1 0x00 000024fb: PUSH1 0x40 000024fd: DUP5 000024fe: DUP7 000024ff: SUB 00002500: SLT 00002501: ISZERO 00002502: PUSH2 0x250a 00002505: JUMPI 00002506: PUSH1 0x00 00002508: DUP1 00002509: REVERT 0000250a: JUMPDEST 0000250b: DUP4 0000250c: CALLDATALOAD 0000250d: PUSH8 0xffffffffffffffff 00002516: DUP2 00002517: GT 00002518: ISZERO 00002519: PUSH2 0x2521 0000251c: JUMPI 0000251d: PUSH1 0x00 0000251f: DUP1 00002520: REVERT 00002521: JUMPDEST 00002522: PUSH2 0x252d 00002525: DUP7 00002526: DUP3 00002527: DUP8 00002528: ADD 00002529: PUSH2 0x2457 0000252c: JUMP 0000252d: JUMPDEST 0000252e: SWAP1 0000252f: SWAP5 00002530: POP 00002531: SWAP3 00002532: POP 00002533: POP 00002534: PUSH1 0x20 00002536: DUP5 00002537: ADD 00002538: CALLDATALOAD 00002539: PUSH2 0x2541 0000253c: DUP2 0000253d: PUSH2 0x240a 00002540: JUMP 00002541: JUMPDEST 00002542: DUP1 00002543: SWAP2 00002544: POP 00002545: POP 00002546: SWAP3 00002547: POP 00002548: SWAP3 00002549: POP 0000254a: SWAP3 0000254b: JUMP 0000254c: JUMPDEST 0000254d: PUSH1 0x00 0000254f: DUP1 00002550: PUSH1 0x40 00002552: DUP4 00002553: DUP6 00002554: SUB 00002555: SLT 00002556: ISZERO 00002557: PUSH2 0x255f 0000255a: JUMPI 0000255b: PUSH1 0x00 0000255d: DUP1 0000255e: REVERT 0000255f: JUMPDEST 00002560: DUP3 00002561: CALLDATALOAD 00002562: SWAP2 00002563: POP 00002564: PUSH1 0x20 00002566: DUP4 00002567: ADD 00002568: CALLDATALOAD 00002569: PUSH2 0x2571 0000256c: DUP2 0000256d: PUSH2 0x240a 00002570: JUMP 00002571: JUMPDEST 00002572: DUP1 00002573: SWAP2 00002574: POP 00002575: POP 00002576: SWAP3 00002577: POP 00002578: SWAP3 00002579: SWAP1 0000257a: POP 0000257b: JUMP 0000257c: JUMPDEST 0000257d: PUSH1 0x00 0000257f: PUSH1 0x20 00002581: DUP3 00002582: DUP5 00002583: SUB 00002584: SLT 00002585: ISZERO 00002586: PUSH2 0x258e 00002589: JUMPI 0000258a: PUSH1 0x00 0000258c: DUP1 0000258d: REVERT 0000258e: JUMPDEST 0000258f: POP 00002590: CALLDATALOAD 00002591: SWAP2 00002592: SWAP1 00002593: POP 00002594: JUMP 00002595: JUMPDEST 00002596: PUSH1 0x00 00002598: DUP1 00002599: PUSH1 0x40 0000259b: DUP4 0000259c: DUP6 0000259d: SUB 0000259e: SLT 0000259f: ISZERO 000025a0: PUSH2 0x25a8 000025a3: JUMPI 000025a4: PUSH1 0x00 000025a6: DUP1 000025a7: REVERT 000025a8: JUMPDEST 000025a9: POP 000025aa: POP 000025ab: DUP1 000025ac: CALLDATALOAD 000025ad: SWAP3 000025ae: PUSH1 0x20 000025b0: SWAP1 000025b1: SWAP2 000025b2: ADD 000025b3: CALLDATALOAD 000025b4: SWAP2 000025b5: POP 000025b6: JUMP 000025b7: JUMPDEST 000025b8: PUSH1 0x00 000025ba: DUP1 000025bb: PUSH1 0x40 000025bd: DUP4 000025be: DUP6 000025bf: SUB 000025c0: SLT 000025c1: ISZERO 000025c2: PUSH2 0x25ca 000025c5: JUMPI 000025c6: PUSH1 0x00 000025c8: DUP1 000025c9: REVERT 000025ca: JUMPDEST 000025cb: DUP3 000025cc: CALLDATALOAD 000025cd: PUSH2 0x25d5 000025d0: DUP2 000025d1: PUSH2 0x240a 000025d4: JUMP 000025d5: JUMPDEST 000025d6: SWAP5 000025d7: PUSH1 0x20 000025d9: SWAP4 000025da: SWAP1 000025db: SWAP4 000025dc: ADD 000025dd: CALLDATALOAD 000025de: SWAP4 000025df: POP 000025e0: POP 000025e1: POP 000025e2: JUMP 000025e3: JUMPDEST 000025e4: PUSH1 0x00 000025e6: DUP1 000025e7: PUSH1 0x40 000025e9: DUP4 000025ea: DUP6 000025eb: SUB 000025ec: SLT 000025ed: ISZERO 000025ee: PUSH2 0x25f6 000025f1: JUMPI 000025f2: PUSH1 0x00 000025f4: DUP1 000025f5: REVERT 000025f6: JUMPDEST 000025f7: DUP3 000025f8: CALLDATALOAD 000025f9: PUSH2 0x2601 000025fc: DUP2 000025fd: PUSH2 0x240a 00002600: JUMP 00002601: JUMPDEST 00002602: SWAP2 00002603: POP 00002604: PUSH1 0x20 00002606: DUP4 00002607: ADD 00002608: CALLDATALOAD 00002609: PUSH2 0x2571 0000260c: DUP2 0000260d: PUSH2 0x240a 00002610: JUMP 00002611: JUMPDEST 00002612: PUSH1 0x00 00002614: DUP1 00002615: PUSH1 0x00 00002617: DUP1 00002618: PUSH1 0x80 0000261a: DUP6 0000261b: DUP8 0000261c: SUB 0000261d: SLT 0000261e: ISZERO 0000261f: PUSH2 0x2627 00002622: JUMPI 00002623: PUSH1 0x00 00002625: DUP1 00002626: REVERT 00002627: JUMPDEST 00002628: DUP5 00002629: CALLDATALOAD 0000262a: SWAP4 0000262b: POP 0000262c: PUSH1 0x20 0000262e: DUP6 0000262f: ADD 00002630: CALLDATALOAD 00002631: PUSH2 0x2639 00002634: DUP2 00002635: PUSH2 0x240a 00002638: JUMP 00002639: JUMPDEST 0000263a: SWAP3 0000263b: POP 0000263c: PUSH1 0x40 0000263e: DUP6 0000263f: ADD 00002640: CALLDATALOAD 00002641: PUSH2 0x2649 00002644: DUP2 00002645: PUSH2 0x240a 00002648: JUMP 00002649: JUMPDEST 0000264a: SWAP4 0000264b: SWAP7 0000264c: SWAP3 0000264d: SWAP6 0000264e: POP 0000264f: SWAP3 00002650: SWAP4 00002651: PUSH1 0x60 00002653: ADD 00002654: CALLDATALOAD 00002655: SWAP3 00002656: POP 00002657: POP 00002658: JUMP 00002659: JUMPDEST 0000265a: PUSH1 0x00 0000265c: DUP1 0000265d: PUSH1 0x20 0000265f: DUP4 00002660: DUP6 00002661: SUB 00002662: SLT 00002663: ISZERO 00002664: PUSH2 0x266c 00002667: JUMPI 00002668: PUSH1 0x00 0000266a: DUP1 0000266b: REVERT 0000266c: JUMPDEST 0000266d: DUP3 0000266e: CALLDATALOAD 0000266f: PUSH8 0xffffffffffffffff 00002678: DUP2 00002679: GT 0000267a: ISZERO 0000267b: PUSH2 0x2683 0000267e: JUMPI 0000267f: PUSH1 0x00 00002681: DUP1 00002682: REVERT 00002683: JUMPDEST 00002684: PUSH2 0x268f 00002687: DUP6 00002688: DUP3 00002689: DUP7 0000268a: ADD 0000268b: PUSH2 0x2457 0000268e: JUMP 0000268f: JUMPDEST 00002690: SWAP1 00002691: SWAP7 00002692: SWAP1 00002693: SWAP6 00002694: POP 00002695: SWAP4 00002696: POP 00002697: POP 00002698: POP 00002699: POP 0000269a: JUMP 0000269b: JUMPDEST 0000269c: PUSH1 0x00 0000269e: DUP1 0000269f: PUSH1 0x00 000026a1: PUSH1 0x40 000026a3: DUP5 000026a4: DUP7 000026a5: SUB 000026a6: SLT 000026a7: ISZERO 000026a8: PUSH2 0x26b0 000026ab: JUMPI 000026ac: PUSH1 0x00 000026ae: DUP1 000026af: REVERT 000026b0: JUMPDEST 000026b1: DUP4 000026b2: CALLDATALOAD 000026b3: PUSH8 0xffffffffffffffff 000026bc: DUP2 000026bd: GT 000026be: ISZERO 000026bf: PUSH2 0x26c7 000026c2: JUMPI 000026c3: PUSH1 0x00 000026c5: DUP1 000026c6: REVERT 000026c7: JUMPDEST 000026c8: PUSH2 0x26d3 000026cb: DUP7 000026cc: DUP3 000026cd: DUP8 000026ce: ADD 000026cf: PUSH2 0x2457 000026d2: JUMP 000026d3: JUMPDEST 000026d4: SWAP1 000026d5: SWAP8 000026d6: SWAP1 000026d7: SWAP7 000026d8: POP 000026d9: PUSH1 0x20 000026db: SWAP6 000026dc: SWAP1 000026dd: SWAP6 000026de: ADD 000026df: CALLDATALOAD 000026e0: SWAP5 000026e1: SWAP4 000026e2: POP 000026e3: POP 000026e4: POP 000026e5: POP 000026e6: JUMP 000026e7: JUMPDEST 000026e8: PUSH1 0x00 000026ea: DUP1 000026eb: PUSH1 0x00 000026ed: PUSH1 0x60 000026ef: DUP5 000026f0: DUP7 000026f1: SUB 000026f2: SLT 000026f3: ISZERO 000026f4: PUSH2 0x26fc 000026f7: JUMPI 000026f8: PUSH1 0x00 000026fa: DUP1 000026fb: REVERT 000026fc: JUMPDEST 000026fd: DUP4 000026fe: CALLDATALOAD 000026ff: PUSH2 0x2707 00002702: DUP2 00002703: PUSH2 0x240a 00002706: JUMP 00002707: JUMPDEST 00002708: SWAP3 00002709: POP 0000270a: PUSH1 0x20 0000270c: DUP5 0000270d: ADD 0000270e: CALLDATALOAD 0000270f: PUSH2 0x2717 00002712: DUP2 00002713: PUSH2 0x240a 00002716: JUMP 00002717: JUMPDEST 00002718: SWAP2 00002719: POP 0000271a: PUSH1 0x40 0000271c: DUP5 0000271d: ADD 0000271e: CALLDATALOAD 0000271f: PUSH2 0x2541 00002722: DUP2 00002723: PUSH2 0x240a 00002726: JUMP 00002727: JUMPDEST 00002728: PUSH1 0x00 0000272a: PUSH1 0x20 0000272c: DUP3 0000272d: DUP5 0000272e: SUB 0000272f: SLT 00002730: ISZERO 00002731: PUSH2 0x2739 00002734: JUMPI 00002735: PUSH1 0x00 00002737: DUP1 00002738: REVERT 00002739: JUMPDEST 0000273a: DUP2 0000273b: CALLDATALOAD 0000273c: PUSH2 0x0ae2 0000273f: DUP2 00002740: PUSH2 0x240a 00002743: JUMP 00002744: JUMPDEST 00002745: PUSH1 0x00 00002747: PUSH1 0x20 00002749: DUP3 0000274a: DUP5 0000274b: SUB 0000274c: SLT 0000274d: ISZERO 0000274e: PUSH2 0x2756 00002751: JUMPI 00002752: PUSH1 0x00 00002754: DUP1 00002755: REVERT 00002756: JUMPDEST 00002757: DUP2 00002758: MLOAD 00002759: PUSH2 0x0ae2 0000275c: DUP2 0000275d: PUSH2 0x240a 00002760: JUMP 00002761: JUMPDEST 00002762: PUSH1 0x00 00002764: PUSH1 0x20 00002766: DUP3 00002767: DUP5 00002768: SUB 00002769: SLT 0000276a: ISZERO 0000276b: PUSH2 0x2773 0000276e: JUMPI 0000276f: PUSH1 0x00 00002771: DUP1 00002772: REVERT 00002773: JUMPDEST 00002774: DUP2 00002775: MLOAD 00002776: DUP1 00002777: ISZERO 00002778: ISZERO 00002779: DUP2 0000277a: EQ 0000277b: PUSH2 0x0ae2 0000277e: JUMPI 0000277f: PUSH1 0x00 00002781: DUP1 00002782: REVERT 00002783: JUMPDEST 00002784: PUSH1 0x20 00002786: DUP1 00002787: DUP3 00002788: MSTORE 00002789: PUSH1 0x2e 0000278b: SWAP1 0000278c: DUP3 0000278d: ADD 0000278e: MSTORE 0000278f: PUSH32 0x496e697469616c697a61626c653a20636f6e747261637420697320616c726561 000027b0: PUSH1 0x40 000027b2: DUP3 000027b3: ADD 000027b4: MSTORE 000027b5: PUSH14 0x191e481a5b9a5d1a585b1a5e9959 000027c4: PUSH1 0x92 000027c6: SHL 000027c7: PUSH1 0x60 000027c9: DUP3 000027ca: ADD 000027cb: MSTORE 000027cc: PUSH1 0x80 000027ce: ADD 000027cf: SWAP1 000027d0: JUMP 000027d1: JUMPDEST 000027d2: PUSH4 0x4e487b71 000027d7: PUSH1 0xe0 000027d9: SHL 000027da: PUSH1 0x00 000027dc: MSTORE 000027dd: PUSH1 0x11 000027df: PUSH1 0x04 000027e1: MSTORE 000027e2: PUSH1 0x24 000027e4: PUSH1 0x00 000027e6: REVERT 000027e7: JUMPDEST 000027e8: DUP1 000027e9: DUP3 000027ea: MUL 000027eb: DUP2 000027ec: ISZERO 000027ed: DUP3 000027ee: DUP3 000027ef: DIV 000027f0: DUP5 000027f1: EQ 000027f2: OR 000027f3: PUSH2 0x0717 000027f6: JUMPI 000027f7: PUSH2 0x0717 000027fa: PUSH2 0x27d1 000027fd: JUMP 000027fe: JUMPDEST 000027ff: DUP2 00002800: DUP2 00002801: SUB 00002802: DUP2 00002803: DUP2 00002804: GT 00002805: ISZERO 00002806: PUSH2 0x0717 00002809: JUMPI 0000280a: PUSH2 0x0717 0000280d: PUSH2 0x27d1 00002810: JUMP 00002811: JUMPDEST 00002812: PUSH1 0x00 00002814: JUMPDEST 00002815: DUP4 00002816: DUP2 00002817: LT 00002818: ISZERO 00002819: PUSH2 0x282c 0000281c: JUMPI 0000281d: DUP2 0000281e: DUP2 0000281f: ADD 00002820: MLOAD 00002821: DUP4 00002822: DUP3 00002823: ADD 00002824: MSTORE 00002825: PUSH1 0x20 00002827: ADD 00002828: PUSH2 0x2814 0000282b: JUMP 0000282c: JUMPDEST 0000282d: POP 0000282e: POP 0000282f: PUSH1 0x00 00002831: SWAP2 00002832: ADD 00002833: MSTORE 00002834: JUMP 00002835: JUMPDEST 00002836: PUSH1 0x00 00002838: DUP2 00002839: MLOAD 0000283a: DUP1 0000283b: DUP5 0000283c: MSTORE 0000283d: PUSH2 0x284d 00002840: DUP2 00002841: PUSH1 0x20 00002843: DUP7 00002844: ADD 00002845: PUSH1 0x20 00002847: DUP7 00002848: ADD 00002849: PUSH2 0x2811 0000284c: JUMP 0000284d: JUMPDEST 0000284e: PUSH1 0x1f 00002850: ADD 00002851: PUSH1 0x1f 00002853: NOT 00002854: AND 00002855: SWAP3 00002856: SWAP1 00002857: SWAP3 00002858: ADD 00002859: PUSH1 0x20 0000285b: ADD 0000285c: SWAP3 0000285d: SWAP2 0000285e: POP 0000285f: POP 00002860: JUMP 00002861: JUMPDEST 00002862: DUP4 00002863: DUP2 00002864: MSTORE 00002865: PUSH1 0x01 00002867: PUSH1 0x01 00002869: PUSH1 0xa0 0000286b: SHL 0000286c: SUB 0000286d: DUP4 0000286e: AND 0000286f: PUSH1 0x20 00002871: DUP3 00002872: ADD 00002873: MSTORE 00002874: PUSH1 0x60 00002876: PUSH1 0x40 00002878: DUP3 00002879: ADD 0000287a: DUP2 0000287b: SWAP1 0000287c: MSTORE 0000287d: PUSH1 0x00 0000287f: SWAP1 00002880: PUSH2 0x288b 00002883: SWAP1 00002884: DUP4 00002885: ADD 00002886: DUP5 00002887: PUSH2 0x2835 0000288a: JUMP 0000288b: JUMPDEST 0000288c: SWAP6 0000288d: SWAP5 0000288e: POP 0000288f: POP 00002890: POP 00002891: POP 00002892: POP 00002893: JUMP 00002894: JUMPDEST 00002895: PUSH1 0x00 00002897: DUP3 00002898: PUSH2 0x28b1 0000289b: JUMPI 0000289c: PUSH4 0x4e487b71 000028a1: PUSH1 0xe0 000028a3: SHL 000028a4: PUSH1 0x00 000028a6: MSTORE 000028a7: PUSH1 0x12 000028a9: PUSH1 0x04 000028ab: MSTORE 000028ac: PUSH1 0x24 000028ae: PUSH1 0x00 000028b0: REVERT 000028b1: JUMPDEST 000028b2: POP 000028b3: DIV 000028b4: SWAP1 000028b5: JUMP 000028b6: JUMPDEST 000028b7: DUP1 000028b8: DUP3 000028b9: ADD 000028ba: DUP1 000028bb: DUP3 000028bc: GT 000028bd: ISZERO 000028be: PUSH2 0x0717 000028c1: JUMPI 000028c2: PUSH2 0x0717 000028c5: PUSH2 0x27d1 000028c8: JUMP 000028c9: JUMPDEST 000028ca: PUSH1 0x00 000028cc: DUP3 000028cd: MLOAD 000028ce: PUSH2 0x28db 000028d1: DUP2 000028d2: DUP5 000028d3: PUSH1 0x20 000028d5: DUP8 000028d6: ADD 000028d7: PUSH2 0x2811 000028da: JUMP 000028db: JUMPDEST 000028dc: SWAP2 000028dd: SWAP1 000028de: SWAP2 000028df: ADD 000028e0: SWAP3 000028e1: SWAP2 000028e2: POP 000028e3: POP 000028e4: JUMP 000028e5: JUMPDEST 000028e6: PUSH32 0x416363657373436f6e74726f6c3a206163636f756e7420000000000000000000 00002907: DUP2 00002908: MSTORE 00002909: PUSH1 0x00 0000290b: DUP4 0000290c: MLOAD 0000290d: PUSH2 0x291d 00002910: DUP2 00002911: PUSH1 0x17 00002913: DUP6 00002914: ADD 00002915: PUSH1 0x20 00002917: DUP9 00002918: ADD 00002919: PUSH2 0x2811 0000291c: JUMP 0000291d: JUMPDEST 0000291e: PUSH17 0x01034b99036b4b9b9b4b733903937b6329 00002930: PUSH1 0x7d 00002932: SHL 00002933: PUSH1 0x17 00002935: SWAP2 00002936: DUP5 00002937: ADD 00002938: SWAP2 00002939: DUP3 0000293a: ADD 0000293b: MSTORE 0000293c: DUP4 0000293d: MLOAD 0000293e: PUSH2 0x294e 00002941: DUP2 00002942: PUSH1 0x28 00002944: DUP5 00002945: ADD 00002946: PUSH1 0x20 00002948: DUP9 00002949: ADD 0000294a: PUSH2 0x2811 0000294d: JUMP 0000294e: JUMPDEST 0000294f: ADD 00002950: PUSH1 0x28 00002952: ADD 00002953: SWAP5 00002954: SWAP4 00002955: POP 00002956: POP 00002957: POP 00002958: POP 00002959: JUMP 0000295a: JUMPDEST 0000295b: PUSH1 0x20 0000295d: DUP2 0000295e: MSTORE 0000295f: PUSH1 0x00 00002961: PUSH2 0x0ae2 00002964: PUSH1 0x20 00002966: DUP4 00002967: ADD 00002968: DUP5 00002969: PUSH2 0x2835 0000296c: JUMP 0000296d: JUMPDEST 0000296e: DUP2 0000296f: MLOAD 00002970: MLOAD 00002971: PUSH1 0x60 00002973: DUP3 00002974: ADD 00002975: SWAP1 00002976: PUSH1 0x0f 00002978: DUP2 00002979: LT 0000297a: PUSH2 0x2993 0000297d: JUMPI 0000297e: PUSH4 0x4e487b71 00002983: PUSH1 0xe0 00002985: SHL 00002986: PUSH1 0x00 00002988: MSTORE 00002989: PUSH1 0x21 0000298b: PUSH1 0x04 0000298d: MSTORE 0000298e: PUSH1 0x24 00002990: PUSH1 0x00 00002992: REVERT 00002993: JUMPDEST 00002994: DUP3 00002995: MSTORE 00002996: PUSH1 0x20 00002998: DUP4 00002999: DUP2 0000299a: ADD 0000299b: MLOAD 0000299c: PUSH1 0x01 0000299e: PUSH1 0x01 000029a0: PUSH1 0xa0 000029a2: SHL 000029a3: SUB 000029a4: AND 000029a5: SWAP1 000029a6: DUP4 000029a7: ADD 000029a8: MSTORE 000029a9: PUSH1 0x40 000029ab: SWAP3 000029ac: DUP4 000029ad: ADD 000029ae: MLOAD 000029af: ISZERO 000029b0: ISZERO 000029b1: SWAP3 000029b2: SWAP1 000029b3: SWAP2 000029b4: ADD 000029b5: SWAP2 000029b6: SWAP1 000029b7: SWAP2 000029b8: MSTORE 000029b9: SWAP1 000029ba: JUMP 000029bb: JUMPDEST 000029bc: PUSH4 0x4e487b71 000029c1: PUSH1 0xe0 000029c3: SHL 000029c4: PUSH1 0x00 000029c6: MSTORE 000029c7: PUSH1 0x32 000029c9: PUSH1 0x04 000029cb: MSTORE 000029cc: PUSH1 0x24 000029ce: PUSH1 0x00 000029d0: REVERT 000029d1: JUMPDEST 000029d2: PUSH4 0x4e487b71 000029d7: PUSH1 0xe0 000029d9: SHL 000029da: PUSH1 0x00 000029dc: MSTORE 000029dd: PUSH1 0x41 000029df: PUSH1 0x04 000029e1: MSTORE 000029e2: PUSH1 0x24 000029e4: PUSH1 0x00 000029e6: REVERT 000029e7: JUMPDEST 000029e8: PUSH1 0x00 000029ea: DUP2 000029eb: PUSH2 0x29f6 000029ee: JUMPI 000029ef: PUSH2 0x29f6 000029f2: PUSH2 0x27d1 000029f5: JUMP 000029f6: JUMPDEST 000029f7: POP 000029f8: PUSH1 0x00 000029fa: NOT 000029fb: ADD 000029fc: SWAP1 000029fd: JUMP 000029fe: JUMPDEST 000029ff: PUSH4 0x4e487b71 00002a04: PUSH1 0xe0 00002a06: SHL 00002a07: PUSH1 0x00 00002a09: MSTORE 00002a0a: PUSH1 0x31 00002a0c: PUSH1 0x04 00002a0e: MSTORE 00002a0f: PUSH1 0x24 00002a11: PUSH1 0x00 00002a13: REVERT 00002a14: INVALID 00002a15: PUSH20 0x3bac3dca102687aa08c854c5f9067fc424f98fd8 00002a2a: UNKNOWN(0xE9) 00002a2b: UNKNOWN(0x0E) 00002a2c: COINBASE 00002a2d: UNKNOWN(0xAD) 00002a2e: PUSH12 0x73aecc59a4fda26469706673 00002a3b: PC 00002a3c: UNKNOWN(0x22) 00002a3d: SLT 00002a3e: KECCAK256 00002a3f: UNKNOWN(0xE7) 00002a40: UNKNOWN(0x2E) 00002a41: EXTCODEHASH 00002a42: SGT 00002a43: DUP6 00002a44: UNKNOWN(0xB9) 00002a45: UNKNOWN(0xB1) 00002a46: UNKNOWN(0x21) 00002a47: UNKNOWN(0xAB) 00002a48: UNKNOWN(0x25) 00002a49: DUP9 00002a4a: JUMPDEST 00002a4b: JUMP 00002a4c: PUSH21 0xc62d66b957590dc193eeba8176ac32bf4d1764736f 00002a62: PUSH13
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| high | other | detector | Untrusted CALL target/value reachable | 60 | no | no |
viewtrace_id: 0x9fa23b641eaae52469043bdc22e14c357eaa8b274c925bc7fa2e9e1b12301ab6
call_targets:
0x29353f77c6b0d3772d73e708cc8e1fca08c80c11
target_varies:
no
classification:
constant_target
validation_json{
"sink": "CALL",
"errors": 0,
"status": "sink_reached",
"attempts": 1,
"trace_id": "0x9fa23b641eaae52469043bdc22e14c357eaa8b274c925bc7fa2e9e1b12301ab6",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x29353f77c6b0d3772d73e708cc8e1fca08c80c11"
],
"matched_probe": null,
"target_varies": false,
"classification": "constant_target"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0xc80493cf",
"selector": "0xc80493cf",
"calldata_variants": [
"0xc80493cf",
"0xc80493cf0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xca15c873",
"selector": "0xca15c873",
"calldata_variants": [
"0xca15c873",
"0xca15c8730000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xd547741f",
"selector": "0xd547741f",
"calldata_variants": [
"0xd547741f",
"0xd547741f0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xe91d6390",
"selector": "0xe91d6390",
"calldata_variants": [
"0xe91d6390",
"0xe91d63900000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xff55cd40",
"selector": "0xff55cd40",
"calldata_variants": [
"0xff55cd40",
"0xff55cd400000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xb0cba84e",
"selector": "0xb0cba84e",
"calldata_variants": [
"0xb0cba84e",
"0xb0cba84e0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xbbc4e8c2",
"selector": "0xbbc4e8c2",
"calldata_variants": [
"0xbbc4e8c2",
"0xbbc4e8c20000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xc0c53b8b",
"selector": "0xc0c53b8b",
"calldata_variants": [
"0xc0c53b8b",
"0xc0c53b8b0000000000000000000000000000000000000000000000000000000000000000"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 2150,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 4295,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 5857,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
}
],
"call_count": 5,
"guards_detected": [],
"untrusted_call_count": 5
}
|
| high | other | slither | Wallets.refundGasBySchain(bytes32,address,uint256,bool) (contracts/test/TestWallets.sol#53-68) sends eth to arbitrary user | 85 | no | — |
viewevidence_json{
"impact": "High",
"detector": "arbitrary-send-eth",
"elements": [
{
"name": "refundGasBySchain",
"type": "function",
"source_mapping": {
"lines": [
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68
],
"start": 1776,
"length": 531,
"ending_column": 6,
"is_dependency": false,
"filename_short": "contracts/test/TestWallets.sol",
"starting_column": 5,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/TestWallets.sol",
"filename_relative": "contracts/test/TestWallets.sol"
},
"type_specific_fields": {
"parent": {
"name": "Wallets",
"type": "contract",
"source_mapping": {
"lines": [
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80
],
"start": 1320,
"length": 1548,
"ending_column": 2,
"is_dependency": false,
"filename_short": "contracts/test/TestWallets.sol",
"starting_column": 1,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/TestWallets.sol",
"filename_relative": "contracts/test/TestWallets.sol"
}
},
"signature": "refundGasBySchain(bytes32,address,uint256,bool)"
}
},
{
"name": "spender.transfer(amount)",
"type": "node",
"source_mapping": {
"lines": [
67
],
"start": 2276,
"length": 24,
"ending_column": 33,
"is_dependency": false,
"filename_short": "contracts/test/TestWallets.sol",
"starting_column": 9,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/TestWallets.sol",
"filename_relative": "contracts/test/TestWallets.sol"
},
"type_specific_fields": {
"parent": {
"name": "refundGasBySchain",
"type": "function",
"source_mapping": {
"lines": [
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68
],
"start": 1776,
"length": 531,
"ending_column": 6,
"is_dependency": false,
"filename_short": "contracts/test/TestWallets.sol",
"starting_column": 5,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/TestWallets.sol",
"filename_relative": "contracts/test/TestWallets.sol"
},
"type_specific_fields": {
"parent": {
"name": "Wallets",
"type": "contract",
"source_mapping": {
"lines": [
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80
],
"start": 1320,
"length": 1548,
"ending_column": 2,
"is_dependency": false,
"filename_short": "contracts/test/TestWallets.sol",
"starting_column": 1,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/TestWallets.sol",
"filename_relative": "contracts/test/TestWallets.sol"
}
},
"signature": "refundGasBySchain(bytes32,address,uint256,bool)"
}
}
}
}
],
"locations": [
{
"file": "contracts/test/TestWallets.sol",
"name": "refundGasBySchain",
"type": "function",
"lines": [
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68
]
},
{
"file": "contracts/test/TestWallets.sol",
"name": "spender.transfer(amount)",
"type": "node",
"lines": [
67
]
}
],
"description": "Wallets.refundGasBySchain(bytes32,address,uint256,bool) (contracts/test/TestWallets.sol#53-68) sends eth to arbitrary user\n\tDangerous calls:\n\t- spender.transfer(amount) (contracts/test/TestWallets.sol#67)"
}
|
| high | other | detector | ETH value transfer possible | 55 | no | no |
viewtrace_id: 0x9fa23b641eaae52469043bdc22e14c357eaa8b274c925bc7fa2e9e1b12301ab6
call_targets:
0x29353f77c6b0d3772d73e708cc8e1fca08c80c11
target_varies:
no
classification:
constant_target
validation_json{
"sink": "CALL",
"errors": 0,
"status": "sink_reached",
"attempts": 1,
"trace_id": "0x9fa23b641eaae52469043bdc22e14c357eaa8b274c925bc7fa2e9e1b12301ab6",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x29353f77c6b0d3772d73e708cc8e1fca08c80c11"
],
"matched_probe": null,
"target_varies": false,
"classification": "constant_target"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0xc80493cf",
"selector": "0xc80493cf",
"calldata_variants": [
"0xc80493cf",
"0xc80493cf0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xca15c873",
"selector": "0xca15c873",
"calldata_variants": [
"0xca15c873",
"0xca15c8730000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xd547741f",
"selector": "0xd547741f",
"calldata_variants": [
"0xd547741f",
"0xd547741f0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xe91d6390",
"selector": "0xe91d6390",
"calldata_variants": [
"0xe91d6390",
"0xe91d63900000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xff55cd40",
"selector": "0xff55cd40",
"calldata_variants": [
"0xff55cd40",
"0xff55cd400000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xb0cba84e",
"selector": "0xb0cba84e",
"calldata_variants": [
"0xb0cba84e",
"0xb0cba84e0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xbbc4e8c2",
"selector": "0xbbc4e8c2",
"calldata_variants": [
"0xbbc4e8c2",
"0xbbc4e8c20000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xc0c53b8b",
"selector": "0xc0c53b8b",
"calldata_variants": [
"0xc0c53b8b",
"0xc0c53b8b0000000000000000000000000000000000000000000000000000000000000000"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 2150,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 4295,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 5857,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
}
],
"eth_value_calls": 5,
"guards_detected": []
}
|
| high | other | codex | ERC20 bridge accounting trusts the requested amount instead of the amount actually received | 85 | no | — |
viewevidence_json{
"evidence": "On mainnet, the code builds the outbound message and increments `transferredAmount` using the caller-supplied `amount`, then performs `safeTransferFrom` with no balance-delta check. On schain-native ERC20 transfers, `_saveTransferredAmount(..., amount)` is also done before `transferFrom`, again assuming the nominal amount was received.",
"locations": [
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:698",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:704",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:705",
"contracts/schain/TokenManagers/TokenManagerERC20.sol:339",
"contracts/schain/TokenManagers/TokenManagerERC20.sol:348",
"contracts/schain/TokenManagers/TokenManagerERC20.sol:350"
],
"recommendation": "Measure `balanceBefore`/`balanceAfter` around every ERC20 pull and bridge only the actual received amount. Revert if the received amount is smaller than requested unless the token type is explicitly unsupported. Apply the same balance-delta accounting anywhere ERC20s are locked rather than burned.",
"exploit_scenario": "A user bridges a fee-on-transfer or deflationary ERC20. `DepositBoxERC20` records and messages the full `amount` before/without checking how many tokens the bridge actually received. The destination chain credits the full amount, but the source bridge locked less. The attacker can later exit the full credited balance and drain other users' liquidity or leave the bridge permanently undercollateralized. The same nominal-amount assumption exists in the schain-native ERC20 path when a token is locked for schain-to-schain transfer."
}
|
| medium | reentrancy | slither | Reentrancy in FallbackEthTester.receive() (contracts/test/FallbackEthTester.sol#55-62): | 75 | no | — |
viewevidence_json{
"impact": "Medium",
"detector": "reentrancy-no-eth",
"elements": [
{
"name": "receive",
"type": "function",
"source_mapping": {
"lines": [
55,
56,
57,
58,
59,
60,
61,
62
],
"start": 1746,
"length": 336,
"ending_column": 6,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 5,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
},
"type_specific_fields": {
"parent": {
"name": "FallbackEthTester",
"type": "contract",
"source_mapping": {
"lines": [
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77
],
"start": 1231,
"length": 1286,
"ending_column": 2,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 1,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
}
},
"signature": "receive()"
}
},
{
"name": "communityPool.withdrawFunds(schainName,balance)",
"type": "node",
"source_mapping": {
"lines": [
59
],
"start": 1977,
"length": 48,
"ending_column": 61,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 13,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
},
"additional_fields": {
"underlying_type": "external_calls"
},
"type_specific_fields": {
"parent": {
"name": "receive",
"type": "function",
"source_mapping": {
"lines": [
55,
56,
57,
58,
59,
60,
61,
62
],
"start": 1746,
"length": 336,
"ending_column": 6,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 5,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
},
"type_specific_fields": {
"parent": {
"name": "FallbackEthTester",
"type": "contract",
"source_mapping": {
"lines": [
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77
],
"start": 1231,
"length": 1286,
"ending_column": 2,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 1,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
}
},
"signature": "receive()"
}
}
}
},
{
"name": "_receiveInProgress = false",
"type": "node",
"source_mapping": {
"lines": [
60
],
"start": 2039,
"length": 26,
"ending_column": 39,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 13,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
},
"additional_fields": {
"variable_name": "_receiveInProgress",
"underlying_type": "variables_written"
},
"type_specific_fields": {
"parent": {
"name": "receive",
"type": "function",
"source_mapping": {
"lines": [
55,
56,
57,
58,
59,
60,
61,
62
],
"start": 1746,
"length": 336,
"ending_column": 6,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 5,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
},
"type_specific_fields": {
"parent": {
"name": "FallbackEthTester",
"type": "contract",
"source_mapping": {
"lines": [
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77
],
"start": 1231,
"length": 1286,
"ending_column": 2,
"is_dependency": false,
"filename_short": "contracts/test/FallbackEthTester.sol",
"starting_column": 1,
"filename_absolute": "/tmp/slither-3rzqsamt/contracts/test/FallbackEthTester.sol",
"filename_relative": "contracts/test/FallbackEthTester.sol"
}
},
"signature": "receive()"
}
}
}
}
],
"locations": [
{
"file": "contracts/test/FallbackEthTester.sol",
"name": "receive",
"type": "function",
"lines": [
55,
56,
57,
58,
59,
60,
61,
62
]
},
{
"file": "contracts/test/FallbackEthTester.sol",
"name": "communityPool.withdrawFunds(schainName,balance)",
"type": "node",
"lines": [
59
]
},
{
"file": "contracts/test/FallbackEthTester.sol",
"name": "_receiveInProgress = false",
"type": "node",
"lines": [
60
]
}
],
"description": "Reentrancy in FallbackEthTester.receive() (contracts/test/FallbackEthTester.sol#55-62):\n\tExternal calls:\n\t- communityPool.withdrawFunds(schainName,balance) (contracts/test/FallbackEthTester.sol#59)\n\tState variables written after the call(s):\n\t- _receiveInProgress = false (contracts/test/FallbackEthTester.sol#60)\n\tFallbackEthTester._receiveInProgress (contracts/test/FallbackEthTester.sol#42) can be used in cross function reentrancies:\n\t- FallbackEthTester.receive() (contracts/test/FallbackEthTester.sol#55-62)"
}
|
| medium | other | codex | Delayed ERC20 withdrawals clear user claims before confirming token delivery | 75 | no | — |
viewevidence_json{
"evidence": "`retrieveFor` removes or marks transfers as `COMPLETED` before calling `_doNTransfers`. `_doNTransfers` catches transfer failures and only emits `TransferSkipped`, without restoring the queue entry or status.",
"locations": [
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:631",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:635",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:651",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:734",
"contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:737"
],
"recommendation": "Do not mutate delayed-transfer state until the token transfer succeeds. Revert failed payouts, or leave the transfer pending so the user can retry later. If partial progress is needed, persist an explicit failed state with an admin/user recovery path instead of deleting the claim.",
"exploit_scenario": "When a delayed transfer becomes withdrawable, `retrieveFor` marks it completed or deletes it from the queue before attempting the ERC20 transfer. If the token transfer then fails, the call is swallowed and only `TransferSkipped` is emitted. A token admin can pause or blacklist transfers right before unlock, or a nonstandard token can fail transfer, causing the receiver's claim to be irreversibly erased while the tokens remain stuck in the bridge contract."
}
|
| low | oracle | codex | `CommunityLocker.setGasPrice` accepts arbitrary caller-supplied oracle values | 65 | no | — |
viewevidence_json{
"evidence": "The function has no access-control modifier, the signature argument is unnamed/unused, and the intended `messageProxy.verifySignature(...)` check is commented out.",
"locations": [
"contracts/schain/CommunityLocker.sol:252",
"contracts/schain/CommunityLocker.sol:257",
"contracts/schain/CommunityLocker.sol:262",
"contracts/schain/CommunityLocker.sol:272"
],
"recommendation": "Require a verified signature or strict role-based authorization before updating oracle state. If the oracle is not live yet, disable the entrypoint rather than accepting unauthenticated writes.",
"exploit_scenario": "Any account can update `mainnetGasPrice` and `gasPriceTimestamp` by calling `setGasPrice`; the signature parameter is unused and the verification check is commented out. Today this state is not consumed elsewhere in first-party code, so impact is limited, but if operators or future upgrades rely on it, an attacker can feed arbitrary prices and timestamps."
}
|
| info | other | cast | Heavy EXTCODE*/BALANCE usage | 55 | no | — |
viewevidence_json{
"notes": "frequent external code or balance checks; may indicate introspection or validation logic",
"ext_balance_count": 8
}
|