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?

5
  • 1
    What is contract? Commented Mar 19, 2020 at 15:39
  • @goodvibration updated the question. Is it more clear?
    – Senju
    Commented Mar 19, 2020 at 15:44
  • What is MultiSigWallet??? Commented Mar 19, 2020 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
    Commented Mar 19, 2020 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
    Commented Mar 22, 2020 at 13:10

1 Answer 1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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