0

Facing a nasty bug and could really use a pair of fresh eyes.

I have a payable function that is somehow taking twice the value sent to it by the sender, from the sender. Specifically, it appears to be a call within the payable function to a library method that is incurring the second "charge", if you will.

Here's an excerpt of the parent contract with the payable function, Remittance.sol:

pragma solidity ^0.4.8;

import "./Owned.sol";
import "./Data.sol";
import "./Util.sol"; 

contract Remittance is Owned {
    Data.LockBoxes lockBox; 
    Data.LockBoxIndex lockBoxIndex;

    modifier stopInEmergency 
    { 
        if(stopped) throw;
        _; 
    }

    function createLockBox(
        address _receiver,
        bytes32 _password1, 
        bytes32 _password2)   
        stopInEmergency      
        payable
        public 
        returns (bool)
    {
        uint amount = msg.value - ownerFee;         

        // After Data.insert() is invoked, `msg.value` is taken from `msg.sender` again
        if(Data.insert(lockBox, lockBoxIndex, _receiver, msg.sender, amount, _password1, _password2))
        {
            LogLockBoxCreated(_receiver, amount, true);
            deposit(owner, ownerFee);            
            return true;
        } 
        else 
        {
            LogLockBoxCreated(_receiver, amount, false);
            throw;
        }
    }    

Here's a portion of the library code, Data.sol:

pragma solidity ^0.4.8;

library Data {

  struct LockBox {
    address creator; 
    uint amount; 
    bytes32 password1; 
    bytes32 password2;
    uint creationTime;
    bool active;
    uint index;        
  }        

  struct LockBoxes { 
      mapping(address => LockBox) boxes; 
  } 

  struct LockBoxIndex { 
      address[] boxIndex; 
  }

  function insert(
      LockBoxes storage s1, 
      LockBoxIndex storage s2,
      address _receiver,
      address _creator,
      uint _amount, 
      bytes32 _password1, 
      bytes32 _password2)
      public
      returns (bool)
  {
      if (s1.boxes[_receiver].active)
           return false;
      s1.boxes[_receiver] = LockBox(_creator, _amount, _password1, _password2, now, true, s2.boxIndex.push(_receiver) - 1);
      return true;
  }  
}

And then, in a truffle test...

remittance.createLockBox.sendTransaction(beneficiary, p1_hash, p2_hash, { from: creator, value: amount })

If amount in the transaction above is 2 ether, then the contract will be paid 4 ether by the sender creator!

Many thanks in advance.

  • What does deposit do? If you sent 2 ether then the contract cannot spent more than 2 ethers from your account, if the contract has a balance it can use it whole. Are you testing with testrpc or with a testnet? – Ismael Jun 19 '17 at 1:51
  • Sorry. Left out deposit for brevity. It just adds a uint value to a mapping. pendingWithdrawals[_account] += _deposit; I'm uing testrpc. "If you sent 2 ether then the contract cannot spent more than 2 ethers from your account" Right? And yet, somehow... it does! – Max Jun 19 '17 at 6:39
2

OK. I'm not going out of my mind. The sender really was getting double-dipped, but oops... looks like I'd better update my copy of testrpc.

The problem is down to a bug in ethereumjs-vm

runCall invoked twice for DELEGATECALL #82

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.