Solidity
我無法從契約中獲得 ERC20 代幣掃描工作
我在下面寫了這個合約,它將創建一個生成使用者存款地址的工廠合約。使用者地址會將任何存款轉發給工廠合約上的授權呼叫者,我還創建了一個函式,可以從使用者的存款錢包中清除 ERC20 代幣。
我的問題是掃描功能似乎每次都失敗,我不知道為什麼!
pragma solidity 0.4.21; //The Factory Contract contract Factory { //Contract Owner address public owner; //The authorized caller to the Users accounts address public authorizedCaller; //The suggested Owner Candidate address private ownerCandidate; //The suggested authorized Caller Candidate address private authorizedCallerCandidate; // contains user wallets mapping (address => bool) public UserWallets; /* the owner Candidate hash of the random generated 256 bit key using keccak256 (web3.sha3) */ bytes32 private ownerCandidateKeyHash; /* the authorized Caller Candidat hash of the random generated 256 bit key using keccak256 (web3.sha3) */ bytes32 private authorizedCallerCandidateKeyHash; // a deposit event to a user contract address event Transaction(address from, address to, uint256 value); // event about an accepted new owner event NewOwner(address owner); // event about a new accepted authorized caller event NewAuthorizedCaller(address authorizedCaller); //event about a new generated user address event NewUserWallet(address newWallet); function Factory() public { owner = msg.sender; authorizedCaller = msg.sender; } // the only owner modifier modifier onlyOwner { assert(msg.sender == owner); _; } // the only authorized called modifier modifier onlyAuthorizedCaller { assert(msg.sender == authorizedCaller); _; } modifier onlyUserWallets { assert(UserWallets[msg.sender] == true); _; } // the only owner candidtate modifier modifier onlyOwnerCandidate(bytes32 key) { assert(msg.sender == ownerCandidate); assert(keccak256(key) == ownerCandidateKeyHash); _; } // the only authorized caller candidtate modifier modifier onlyAuthorizedCallerCandidate(bytes32 key) { assert(msg.sender == authorizedCallerCandidate); assert(keccak256(key) == authorizedCallerCandidateKeyHash); _; } /* transfer ownership function, create a transfer proposal that needs to be accepted by the new owner candidtate: candidate address is needed keyHash: generate a 256 bit key and hash it using keccak256 (web3.sha3) share the key with the candidate through a secure communication channel */ function transferOwnership(address candidate, bytes32 keyHash) public onlyOwner { ownerCandidate = candidate; ownerCandidateKeyHash = keyHash; } /* the candidate needs to have the key that generates the correct hash to be able to accept ownership of the contract, the key should be communicated through secure channels */ function acceptOwnership(bytes32 key) external onlyOwnerCandidate(key) { owner = ownerCandidate; emit NewOwner(ownerCandidate); } /* change the Authorized caller function, create a transfer proposal that needs to be accepted by the new Authorized caller candidtate: candidate address is needed keyHash: generate a 256 bit key and hash it using keccak256 (web3.sha3) share the key with the candidate through a secure communication channel */ function changeAuthorizedCaller(address candidate, bytes32 keyHash) public onlyOwner { authorizedCallerCandidate = candidate; authorizedCallerCandidateKeyHash = keyHash; } /* the candidate needs to have the key that generates the correct hash to be able to accept ownership of the contract, the key should be communicated through secure channels */ function acceptAuthorization(bytes32 key) external onlyAuthorizedCallerCandidate(key) { authorizedCaller = authorizedCallerCandidate; emit NewAuthorizedCaller(authorizedCallerCandidate); } // this function generates users wallets function CreateNewUserWallet() public onlyAuthorizedCaller returns (address newWallet) { newWallet = new UserWallet(address(this)); UserWallets[newWallet] = true; emit NewUserWallet(newWallet); } // in case we need to make some calls using this contract function execute(address to, uint256 value, bytes data) public onlyAuthorizedCaller { require(to.call.value(value)(data)); } // the function logs value transactions to a user wallet function LogTransaction(address from, address to, uint256 value) external onlyUserWallets { emit Transaction(from, to, value); } } // User wallet contract UserWallet { Factory FactoryContract; /* a Modifier to make sure that ony the Authorized caller can call some functions */ function UserWallet(address _FactoryContract) public { FactoryContract = Factory(_FactoryContract); } modifier onlyAuthorizedCaller { assert(msg.sender == FactoryContract.authorizedCaller()); _; } /* Allow payments and sweep them automatically to the Authorized caller's address */ function() public payable { if (msg.value > 0) { FactoryContract.authorizedCaller().transfer(msg.value); FactoryContract.LogTransaction(msg.sender, this, msg.value); } } /* Sweep ERC20 tokens sent to this wallet by simple providing the token Contract Address (ERC20 contract address) */ function SweepTokens(address tokenContractAddress) public onlyAuthorizedCaller { ERC20Interface Token = ERC20Interface(tokenContractAddress); address Wallet = address(this); address AuthorizedCaller = FactoryContract.authorizedCaller(); uint256 TokenBalance = Token.balanceOf(Wallet); if (TokenBalance > 0) { require(Token.transfer(AuthorizedCaller, TokenBalance)); } } /* execute function allow us to still execute any call on this contract making it almost like a normal account address */ function execute(address to, uint256 value, bytes data) public onlyAuthorizedCaller { require(to.call.value(value)(data)); } } // ERC20 Interface contract ERC20Interface { function totalSupply() public constant returns (uint); function balanceOf(address tokenOwner) public constant returns (uint balance); function allowance(address tokenOwner, address spender) public constant returns (uint remaining); function transfer(address to, uint tokens) public returns (bool success); function approve(address spender, uint tokens) public returns (bool success); function transferFrom(address from, address to, uint tokens) public returns (bool success); event Transfer(address indexed from, address indexed to, uint tokens); event Approval(address indexed tokenOwner, address indexed spender, uint tokens); }
我發現了問題所在,我正在測試的 ERC20 代幣似乎不允許掃描確切的餘額,如果我減去一個小數點值,轉移就可以正常工作。
uint256 TokenBalance = Token.balanceOf(Wallet) - 1;