Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable amount/asset forwarding in tx params #167

Merged
merged 3 commits into from
Mar 24, 2022

Conversation

digorithm
Copy link
Member

@digorithm digorithm commented Mar 24, 2022

Adds a CallParameters to support forwarding amount and asset_id through a new chain method: call_params().

It also extends the generated script and script_data to enable this support.

Example:

let tx_params = TxParameters::new(None, Some(1_000_000), None);

// Forwarding 1 (Some(1)) coin of type `NATIVE_ASSET_ID` (`0x00...`).
let call_params = CallParameters::new(Some(1), None);

let response = instance
    .get_msg_amount()
    .tx_params(tx_params) // Set the transaction params
    .call_params(call_params) // Set the call params
    .call()
    .await
    .unwrap();
CallResponse { value: 1, receipts: [Call { id: eb41245813e928b57b2c57ee14b0dfa4073687d3c69792f8bc14beed6825ffae, to: 
eb41245813e928b57b2c57ee14b0dfa4073687d3c69792f8bc14beed6825ffae, amount: 1, asset_id: 
0000000000000000000000000000000000000000000000000000000000000000, gas: 999967, a: 2830212025, b: 1, pc: 1712, is: 1712 }] }

In Sway, this amount is accessible through the standard library method msg_amount(), e.g.:

abi TestFuelCoin {
    fn get_msg_amount() -> u64;
}

impl TestFuelCoin for Contract {
    fn get_msg_amount() -> u64 {
        msg_amount()
    }
}

Closes #159.

@digorithm digorithm self-assigned this Mar 24, 2022
@digorithm digorithm added the enhancement New feature or request label Mar 24, 2022
Comment on lines 83 to 128
let script_len = 56;
let script_data_offset = VM_TX_MEMORY + Transaction::script_offset() + script_len;
let script_data_offset = script_data_offset as Immediate12;

// The offset that locates the asset ID in the script data.
// It goes from the beginning of `script_data` to `32`.
let asset_id_offset = 32;

// Script to call the contract. The offset that points to the `script_data` is loaded at the
// register `0x10`. Note that we're picking `0x10` simply because it could be any
// register `0x12`. Note that we're picking `0x12` simply because it could be any
// non-reserved register. Then, we use the Opcode to call a contract: `CALL` pointing at the
// register that we loaded the `script_data` at.

// The `iter().collect()` does the Opcode->u8 conversion
#[allow(clippy::iter_cloned_collect)]
let script = vec![
Opcode::ADDI(0x10, REG_ZERO, script_data_offset),
// @todo currently there's no way to forward an amount.
// This would be done by programmatically changing
// $rB (`REG_ZERO` right now) to actually point to an
// amount. This would forward the amount in $rB using
// $rC as the asset_id.
Opcode::CALL(0x10, REG_ZERO, 0x10, REG_CGAS),
// Setting `0x10` to point to the 32-byte asset ID of the amount to forward.
Opcode::ADDI(0x10, REG_ZERO, asset_id_offset),
// Setting `0x11` to hold the amount of of coins to forward.
Opcode::ADDI(0x11, REG_ZERO, tx_parameters.amount as Immediate12),
// Setting `0x12` to the `script_data`, defined down below but
// we already know its length.
Opcode::ADDI(0x12, REG_ZERO, script_data_offset),
Opcode::CALL(0x12, 0x11, 0x10, REG_CGAS),
Opcode::RET(REG_RET),
Opcode::NOOP,
]
.iter()
.copied()
.collect::<Vec<u8>>();

assert_eq!(script.len(), script_len, "Script length *must* be 16");
assert_eq!(
script.len(),
script_len - asset_id_offset as usize,
"Script length *must* be 24"
);

// `script_data` consists of:
// 1. Contract ID (ContractID::LEN);
// 2. Function selector (1 * WORD_SIZE);
// 3. Calldata offset, if it has structs as input,
// 1. Asset ID to be forwarded
// 2. Contract ID (ContractID::LEN);
// 3. Function selector (1 * WORD_SIZE);
// 4. Calldata offset, if it has structs as input,
// computed as `script_data_offset` + ContractId::LEN
// + 2 * WORD_SIZE;
// 4. Encoded arguments.
// 5. Encoded arguments.
let mut script_data: Vec<u8> = vec![];

script_data.extend(tx_parameters.asset_id.to_vec());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luizstacio @AlicanC This whole section here is what's needed on fuels-ts to implement the same thing. Let me know if it's not clear enough and/or if you have more questions!

Cargo.lock Outdated Show resolved Hide resolved
fuels-contract/src/parameters.rs Show resolved Hide resolved
Copy link
Contributor

@adlerjohn adlerjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The core changeset is good, but just to get into a good habit, could you break apart updating fuel-vm, updating tests, fixing unrelated tests, and fixing some constants all into different PRs?

@digorithm
Copy link
Member Author

The core changeset is good, but just to get into a good habit, could you break apart updating fuel-vm, updating tests, fixing unrelated tests, and fixing some constants all into different PRs?

Hmm... All the changes done in this PR are related to each other, I think?

  1. Updating fuel-vm is needed to actually make Enable amount/asset forwarding in tx params work;
  2. Updating tests... also needed for Enable amount/asset forwarding in tx params;
  3. Fixing unrelated tests, they were not unrelated, I think? They were affected by the core changes done here;
  4. Fixing some constants... I added a new one, related to this PR, needed to get Enable amount/asset forwarding in tx params to work.

@digorithm digorithm merged commit 6cbc20e into master Mar 24, 2022
@digorithm digorithm deleted the rodrigo/coin-forwarding branch March 24, 2022 22:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Programmatically set amount and asset to be forwarded in contract calls
2 participants