Solidity

我無法從契約中獲得 ERC20 代幣掃描工作

  • February 21, 2019

我在下面寫了這個合約,它將創建一個生成使用者存款地址的工廠合約。使用者地址會將任何存款轉發給工廠合約上的授權呼叫者,我還創建了一個函式,可以從使用者的存款錢包中清除 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);
}

ropsten 上的工廠範例

Ropsten 上的使用者錢包範例

掃蕩交易失敗

我發現了問題所在,我正在測試的 ERC20 代幣似乎不允許掃描確切的餘額,如果我減去一個小數點值,轉移就可以正常工作。

uint256 TokenBalance = Token.balanceOf(Wallet) - 1;

引用自:https://ethereum.stackexchange.com/questions/67254