Solidity

使用 .value() 在使用solidity和truffle框架的合約之間匯款時出現編譯錯誤

  • December 27, 2018

親愛的積木建造者!我是這個領域的新手,我想實現我的第一個項目,使用重入來模仿著名的 DAO 攻擊。我編寫了兩個智能合約——DAO 和 Hacker。.value()但是,由於該方法,我無法編譯我的契約。

DAO 包含所有使用者的餘額、地址和姓名

pragma solidity ^0.4.24;
contract Dao {
struct User {
   address addr;
   string name;
   uint balence;
   uint8 flag;
}
....
function addToBalence(string name) public payable{
   if(users[msg.sender].flag != 1) addUser(msg.sender,name,0,1);
   users[msg.sender].balence = users[msg.sender].balence + msg.value;
}

function showBalence() public returns (uint) {
   return users[msg.sender].balence;
}

function withdraw(uint amount) public payable{

   if(users[msg.sender].flag != 1) revert("user does not exist");
   else if (users[msg.sender].balence >= amount){
       msg.sender.call.value(amount)();
       users[msg.sender].balence -= amount;
   }
 }
}

黑客(目前只是普通使用者)假設先存入少量資金,然後使用重入攻擊提取的資金超過他在 DAO 的存款

contract Hacker {
Dao dao;
address userAddress; // the address of the user, so the money can be transfered
string userName;

constructor(string userName, address daoAddress) public {
   dao = Dao(daoAddress);
   userAddress = msg.sender;
   userName = userName;
}

function addToBalence(string name, uint amount) public payable {
   dao.addToBalence(userName).value(msg.value)(); // ERROR HERE!
}

function showBalence() public returns(uint){
   return dao.showBalence();
}

function payout(uint amount) public payable{
   dao.withdraw(amount);
}
}

但是,我addToBalence在 Hacker 的契約中的方法出現錯誤,提示說Member "value" not found or not visible after argument-dependent lookup in tuple() - did you forget the "payable" modifier? dao.addToBalence(userName).value(msg.value)();

我非常困惑,因為我已經在 DAO 和 Hacker 的契約中添加了應付修改器。這是否意味著我的方法很簡單,我無法在我的玩具範例中攻擊 DAO 合約?我哪裡做錯了?

你非常接近,你只需要稍微改變你的外部合約函式呼叫的語法addToBalence(...)

$$ sic $$功能:

//...
function addToBalence(string name, uint amount) public payable {
   dao.addToBalence.value(msg.value)(userName);
}
//...

請注意,我們在之後刪除了第一組括號addToBalence

$$ sic $$& 將其中的參數移到了最後一組括號中。  


 

這是您的契約的完整實現(添加了User映射和缺少的addUser功能以使其成功編譯)而沒有該錯誤消息:

pragma solidity ^0.4.24;

contract Dao {

   mapping (address => User) public users;

   struct User {
       address addr;
       string name;
       uint balence;
       uint8 flag;
   }

   function addUser(address _address, string _name, uint _balence, uint8 _flag) public {
       users[msg.sender].name = _name;
       users[msg.sender].flag = _flag;
       users[msg.sender].addr = _address;
       users[msg.sender].balence = _balence;
   }

   function addToBalence(string name) public payable{
       if(users[msg.sender].flag != 1) addUser(msg.sender,name,0,1);
       users[msg.sender].balence = users[msg.sender].balence + msg.value;
   }

   function showBalence() public returns (uint) {
       return users[msg.sender].balence;
   }

   function withdraw(uint amount) public payable{
       if(users[msg.sender].flag != 1) revert("user does not exist");
       else if (users[msg.sender].balence >= amount){
           msg.sender.call.value(amount)();
           users[msg.sender].balence -= amount;
       }
   }
}

contract Hacker {
   Dao dao;
   address userAddress; // the address of the user, so the money can be transfered
   string userName;

   constructor(string _userName, address daoAddress) public {
       dao = Dao(daoAddress);
       userAddress = msg.sender;
       userName = _userName;
   }

   function addToBalence(string name, uint amount) public payable {
       dao.addToBalence.value(msg.value)(userName); // ERROR HERE!
   }
}

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