2

I am using a standard MultiSigWallet contract. My goal is to create the data parameter with web3, which is used in executeTransaction / external_call (bytes memory data). The transaction should send Ether from the MultiSigWallet to a specific user address.

Solidity

contract MultiSigWallet {
struct Transaction {
    address destination;
    uint256 value;
    bytes data;
    bool executed;
}

/// @dev Allows an owner to submit and confirm a transaction.
/// @param destination Transaction target address.
/// @param value Transaction ether value.
/// @param data Transaction data payload.
/// @return transactionId transactionId Returns transaction ID.
function submitTransaction(address destination,
    uint256 value,
    bytes memory data)
    public
    returns (uint256 transactionId)
{
    transactionId = addTransaction(destination, value, data);
    confirmTransaction(transactionId);
}

/// @dev Allows an owner to confirm a transaction.
/// @param transactionId Transaction ID.
function confirmTransaction(uint256 transactionId)
    public
    ownerExists(msg.sender)
    transactionExists(transactionId)
    notConfirmed(transactionId, msg.sender)
{
    confirmations[transactionId][msg.sender] = true;
    emit Confirmation(msg.sender, transactionId);
    executeTransaction(transactionId);
}

/// @dev Allows anyone to execute a confirmed transaction.
/// @param transactionId Transaction ID.
function executeTransaction(uint256 transactionId)
    public
    ownerExists(msg.sender)
    confirmed(transactionId, msg.sender)
    notExecuted(transactionId)
{
    if (isConfirmed(transactionId)) {
        Transaction storage txn = transactions[transactionId];
        txn.executed = true;
        if (
            external_call(
                txn.destination,
                txn.value,
                txn.data.length,
                txn.data
            )
        ) {
            emit Execution(transactionId);
        } else {
            emit ExecutionFailure(transactionId);
            txn.executed = false;
        }
    }
}

// call has been separated into its own function in order to take advantage
// of the Solidity's code generator to produce a loop that copies tx.data into memory.
function external_call(address destination,
    uint256 value,
    uint256 dataLength,
    bytes memory data)
    internal
    returns (bool)
{
    bool result;
    assembly {
        let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
        let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
        result := call(
            sub(gas(), 34710), // 34710 is the value that solidity is currently emitting
            // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
            // callNewAccountGas (25000, in case the destination address does not exist and needs creating)
            destination,
            value,
            d,
            dataLength, // Size of the input (in bytes) - this is what fixes the padding problem
            x,
            0 // Output is ignored, therefore the output size is zero
        )
    }
    return result;
}

} }

Web3

multisigInstance = MultiSigWallet.new(owners, confirmations);
dataParameter = multisigInstance.contract.transfer.getData(depositAddress, amount);

This code results in error TypeError: Cannot read property 'getData' of undefined

multisigInstance = MultiSigWallet.new(owners, confirmations);    
dataParameter = multisigInstance.contract.methods.transfer(toAddress, amount).encodeABI();

This code results in error results in TypeError: multisigInstance.contract.methods.transfer is not a function

Similar Problems but outdate:

How to transfer ERC20 tokens using web3js

How to send ERC20 token using Web3 API?

eth
  • 85,679
  • 53
  • 285
  • 406
Senju
  • 701
  • 1
  • 15
  • 28
  • 1
    What is contract? – goodvibration Mar 19 '20 at 15:39
  • @goodvibration updated the question. Is it more clear? – Senju Mar 19 '20 at 15:44
  • What is MultiSigWallet??? – goodvibration Mar 19 '20 at 16:45
  • @Senju It appears you are calling transfer in the wrong contract. Perhaps are you trying to call a token transfer owned my a multisig wallet? Then you should call to the token contract not the multisig one. – Ismael Mar 19 '20 at 17:59
  • @Ismael Maybe I was lazy and unclear. ;) Provided more info and the contract code. I am using a standard MultiSigWallet contract. My goal is to create the data parameter with web3, which is used in executeTransaction / external_call (bytes memory data). The transaction should send Ether from the MultiSigWallet to a specific user address. – Senju Mar 22 '20 at 13:10

1 Answers1

4

To send ethers is very simple:

// Submit transfer operation
const receipt = await multisig.submitTransaction(recipient, amount, "").send();

// Obtain transactId from receipt
const transactionId = ...;

// When confirmed by owners majority it will execute

To send ERC20 is slightly more complicated

// Encode ERC20 transfer operation
const data = token.methods.transfer(recipient, amount).encodeABI();

// Submit operation to multisig
await multisig.submitTransaction(token.options.address, 0, data).send();

// Rest is the same as a regular transfer
Ismael
  • 30,570
  • 21
  • 53
  • 96