Skip to content

Safe transaction service reporting incorrect signer when using ledger with proposeTransactionsWithSignature() #22

@zacshowa

Description

@zacshowa

Background

I've been using safe-utils to write a solidity script that involves batching a few transactions and proposing them to a safe wallet like so:

function addToBatch(address target, bytes memory callData) internal {
        batchTargets.push(target);
        batchData.push(callData);
}


function proposeBatchTransaction() internal returns bytes32{
        //Generate transaction target and data arrays for signing.
        bytes memory transactionDataContract1 = abi.encodeCall(ownable2StepContract1.acceptOwnership, ());
        bytes memory transactionDataContract2 = abi.encodeCall(ownable2StepContract2.acceptOwnership, ());
        bytes memory transactionDataContract3 = abi.encodeCall(ownable2StepContract3.acceptOwnership, ());

        addToBatch(address(contract1), transactionDataContract1);
        addToBatch(address(contract2), transactionDataContract2);
        addToBatch(address(contract3), transactionDataContract3);

        //Get composed transaction data
        (address to, bytes memory data) = safe.getProposeTransactionsTargetAndData(batchTargets, batchData);

        // Get signature over transaction so we can propose it to the multisig wallet.

        bytes memory signature = safe.sign(to, data, Enum.Operation.Call, proposerAddress, derivationPath);

        //Use signature to propose transaction to the safe wallet
        bytes32 txHash = safe.proposeTransactionsWithSignature(
            batchTargets,
            batchData,
            proposerAddress,
            signature
        );
        return txHash;
}

The script uses several contract level variables. Namely, batchTargets, batchData, proposerAddress, and derivationPath.
The types associated with these are as follows.

    address[] internal batchTargets;
    bytes[] internal batchData;
    // The following are read in via vm.env* cheatcodes.
    address proposerAddress; // This will be the address of the account stored in the ledger at derivationPath
    string derivationPath;

Issue

From my understanding this should mean while running the script, a user would be using their ledger wallet to sign this batch of transactions, and then have it proposed to the multi-sig wallet, making it visible on their UI.

However, when running the script, I get the following error message from the safe-ui service:

ProposeTransactionFailed(422, "{\"nonFieldErrors\":[\"Signer=0x9999999999999999999999999999999999999999 is not an owner or delegate. Current owners=['0x1111111111111111111111111111111111111111', '0x2222222222222222222222222222222222222222', '0x3333333333333333333333333333333333333333']. Delegates=set()\"]}")

The signer address returned is notably not the address present in the ledger wallet at the derivation path used to sign; furthermore, the signer address isn't present on the ledger at all.

At first I assumed that this was because the script executes some transactions before this step with a different address, so I might have been constructing the signature wrong. However, the first address used for broadcasting in the script is also not the address listed as a signer.

I found a similar issue someone had with a javascript framework for interacting with the safe API. The solution they later posted implies that the signature being generated wrong might cause this issue, but it's not immediately obvious to me how I would be doing that wrong here.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions