patractlabs / redspot

Redspot is an Substrate pallet-contracts (ink!) development environment. Compile your contracts and run them on a different networks. Redspot's core forks from Hardhat but changed a lot to suit substrate.
https://redspot.patract.io/
Other
67 stars 22 forks source link

[support needed] specify contract call originator #104

Closed RoyTimes closed 3 years ago

RoyTimes commented 3 years ago

After https://github.com/patractlabs/redspot/pull/91 It seems like buildTx removed the option to specify which signer is used to sign a transaction? I was a bit confused of how to structure test cases when the contract reacts differently to different signers.

Before, https://github.com/patractlabs/redspot/pull/91 the following code will send on behalf of sender2, while after https://github.com/patractlabs/redspot/pull/91 , {signer: senderX} does not seem to work anymore.

// sender1 deployed the contract
const contractFactory = await getContractFactory('smartcontract', sender1);

// before PR#91
await expect(contract.tx.message(param, { signer: sender2 }))
// sender2 sent the transaction.

// =================

// after PR#91
await expect(contract.tx.message(param, { signer: sender2 }))
// sender1 sent the transaction, instead of sender1, because sender1 deployed the contract.

Please let me know the new way of doing so. I'll temporarily revert to 0.11.4-6 for now.

ii-ii-ii commented 3 years ago

Yes, we just finished the review of the new version of redspot https://polkadot.polkassembly.io/post/457 In the latest version, you will get an error when using signer. The purpose of this is to be able to sign using only the address (because in the new version we support signing via polkadot extension, you can't get the private key when using polkadot extension)

image

And then it's all compatible except for this point you mentioned. If you want to change the signer, you can use connect.

image

https://substrate-contracts-book-patract.vercel.app/redspot/plugin/redspot-patract.html

like:

const newSigner = contract.connect('5G....') or contract.connect(signer)
newSigner.tx.messgae.....

It is similar to the design of ethers https://docs.ethers.io/v5/single-page/#/v5/api/contract/contract/-%23-Contract-connect

RoyTimes commented 3 years ago

Make sense. This sounds like a good approach. Look forwards to it and we will adopt it when it's published. You can close at wish, or keep this issue open for tracking.

ii-ii-ii commented 3 years ago

It has been released. It should be 0.11.5

tk-o commented 3 years ago

Sending value on a TX to a smart contract's method

I have somewhat related question: how do I send value while calling smart contract payable method?

Context

I have been trying to have this solidity contract re-created in ink!.

The functionality allows a user to lock some ETH for some period of time. The Lockdrop contract receives ETH from a user, and then create an instance of a Lock smart contract, that receives all user's funds sent to be locked. The Lock contract instance will allow the owner (the user who locked some ETH) to withdraw them after certain period of time.

Issue

Here's my smart contract method I'd like to send some native token to, and here's how I've been trying to do that.

My transaction always fails, either due to ContractTrapped, or OutOfGas. What should I do differently?


Polkadot.js

I saw an example in polkadot.js docs but I does not seem to be supported by the Redspot SDK — am I right?

// We will use these values for the execution
const value = 0; // only useful on isPayable messages
const gasLimit = 3000n * 1000000n;
const incValue = 1;

// Send the transaction, like elsewhere this is a normal extrinsic
// with the same rules as applied in the API (As with the read example,
// additional params, if required can follow - here only one is needed)
await contract.tx
  .inc({ value, gasLimit }, incValue)
  .signAndSend(alicePair, (result) => {
    if (result.status.isInBlock) {
      console.log('in a block');
    } else if (result.status.isFinalized) {
      console.log('finalized');
    }
  });
ii-ii-ii commented 3 years ago

Sending value on a TX to a smart contract's method

I have somewhat related question: how do I send value while calling smart contract payable method?

Context

I have been trying to have this solidity contract re-created in ink!.

The functionality allows a user to lock some ETH for some period of time. The Lockdrop contract receives ETH from a user, and then create an instance of a Lock smart contract, that receives all user's funds sent to be locked. The Lock contract instance will allow the owner (the user who locked some ETH) to withdraw them after certain period of time.

Issue

Here's my smart contract method I'd like to send some native token to, and here's how I've been trying to do that.

My transaction always fails, either due to ContractTrapped, or OutOfGas. What should I do differently?

Polkadot.js

I saw an example in polkadot.js docs but I does not seem to be supported by the Redspot SDK — am I right?

// We will use these values for the execution
const value = 0; // only useful on isPayable messages
const gasLimit = 3000n * 1000000n;
const incValue = 1;

// Send the transaction, like elsewhere this is a normal extrinsic
// with the same rules as applied in the API (As with the read example,
// additional params, if required can follow - here only one is needed)
await contract.tx
  .inc({ value, gasLimit }, incValue)
  .signAndSend(alicePair, (result) => {
    if (result.status.isInBlock) {
      console.log('in a block');
    } else if (result.status.isFinalized) {
      console.log('finalized');
    }
  });

Like this:

const result = await contract.tx.transfer(someddress, 7, {
gasLimit:'1231231231233123123'
});
tk-o commented 3 years ago

Hey @ii-ii-ii, thank you for a quick reply!

When I use this call:

await lockdropContract.tx.lock(sender.address, 7, {
  gasLimit: '1231231231233123123'
});

I get an error:

Error: Expected 0 arguments to contract message 'lock', found 3

The lock method is not accepting any arguments:

#[ink(message, payable)]
pub fn lock(&mut self) {

Here's a full code of my lock method.

ii-ii-ii commented 3 years ago

Hey @ii-ii-ii, thank you for a quick reply!

When I use this call:

await lockdropContract.tx.lock(sender.address, 7, {
  gasLimit: '1231231231233123123'
});

I get an error:

Error: Expected 0 arguments to contract message 'lock', found 3

The lock method is not accepting any arguments:

#[ink(message, payable)]
pub fn lock(&mut self) {

Here's a full code of my lock method.

Try this:

await lockdropContract.tx.lock({
  gasLimit: '1000000000000'
});
tk-o commented 3 years ago

Ok, here's an example on how to send a tx to contract with some value:

await lockdropContract.tx.lock({
  gasLimit: '1000000000001',
  value: '7 UNIT',
});

image

My only problem now is contract being trapped, but I'll ask about in on ink! issues, and link the response back here for people having this issue in the future.