Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions academy/lending-protocol/contracts/LendingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ contract LendingPool is NilBase, NilTokenBase {
/// @dev The deposited tokens are recorded in the GlobalLedger via an asynchronous call.
function deposit() public payable {
/// Retrieve the tokens being sent in the transaction
Nil.Token[] memory tokens = Nil.txnTokens();
Nil.Token[] memory tokens = Nil.txnTokens(); // TODO: [PoC] Tokens remove it

/// @notice Encoding the call to the GlobalLedger to record the deposit
/// @dev The deposit details (user address, token type, and amount) are encoded for GlobalLedger.
Expand Down Expand Up @@ -215,7 +215,7 @@ contract LendingPool is NilBase, NilTokenBase {
function repayLoan() public payable {
/// @notice Retrieve the tokens being sent in the transaction
/// @dev Retrieves the tokens involved in the repayment.
Nil.Token[] memory tokens = Nil.txnTokens();
Nil.Token[] memory tokens = Nil.txnTokens(); // TODO: [PoC] Tokens remove it

/// @notice Prepare to query the loan details from GlobalLedger
/// @dev Fetches the loan details of the borrower to proceed with repayment.
Expand Down
2 changes: 1 addition & 1 deletion academy/lending-protocol/deep_dive_into_the_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Example:

```solidity
function deposit() public payable {
Nil.Token[] memory tokens = Nil.txnTokens();
Nil.Token[] memory tokens = Nil.txnTokens(); // TODO: [PoC] Tokens remove it
bytes memory callData = abi.encodeWithSignature(
"recordDeposit(address,address,uint256)",
msg.sender,
Expand Down
2 changes: 1 addition & 1 deletion academy/token-split/contracts/tokenSplitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract TokenSplitter is NilBase, NilTokenBase, Ownable, ReentrancyGuard {
if (_recipients.length == 0) revert NoRecipientsSpecified();
if (_recipients.length != _amounts.length) revert ArrayLengthMismatch();

Nil.Token[] memory tokens = Nil.txnTokens();
Nil.Token[] memory tokens = Nil.txnTokens(); // TODO: [PoC] Tokens remove it

uint256 totalAmountToSend = 0;
for (uint256 i = 0; i < _amounts.length; i++) {
Expand Down
1 change: 1 addition & 0 deletions docs/nil/guides/app-migration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -319,5 +319,6 @@ Note that it is also possible to use async calls to send custom tokens between c
```solidity file=../../tests/AsyncToken.sol start=startAsyncTokenContract end=endAsyncTokenContract
```

// TODO: [PoC] Tokens remove it
Tokens can be extracted from any transaction by using `Nil.txnTokens()` and then passed to the `asyncCallWithTokens()` method. When migrating a dApp to =nil;, do not hesitate to deploy contracts on different shards: they will still be able to send and receive tokens from contracts on other shards.

4 changes: 2 additions & 2 deletions docs/nil/smart-contracts/pre-compiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ The function shows how many tokens with the given `id` are held by the contract

## `GET_TRANSACTION_TOKENS`

`GET_TRANSACTION_TOKENS` is the pre-compile used in the `txnTokens()` function.
`GET_TRANSACTION_TOKENS` is the pre-compile used in the `txnTokens()` function. // TODO: [PoC] Tokens remove it

```solidity showLineNumbers
function txnTokens() internal returns(Token[] memory)
function txnTokens() internal returns(Token[] memory) // TODO: [PoC] Tokens remove it
```

The function returns the list of tokens for the current transaction.
Expand Down
2 changes: 1 addition & 1 deletion docs/tests/AsyncToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "@nilfoundation/smart-contracts/contracts/Nil.sol";

contract AsyncTokenSender {
function sendTokenAsync(uint amount, address dst) public {
Nil.Token[] memory tokens = Nil.txnTokens();
Nil.Token[] memory tokens = Nil.txnTokens(); // TODO: [PoC] Tokens remove it
Nil.asyncCallWithTokens(
dst,
msg.sender,
Expand Down
2 changes: 1 addition & 1 deletion docs/tests/SwapMatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ contract SwapMatch is NilBase {
//Create a new swap request
SwapRequest memory newSwapRequest = SwapRequest({
initiator: msg.sender,
token: Nil.txnTokens()[0],
token: Nil.txnTokens()[0], // TODO: [PoC] Tokens remove it
secondTokenId: _secondTokenId,
desiredSecondTokenAmount: _desiredSecondTokenAmount,
isMatched: false
Expand Down
2 changes: 1 addition & 1 deletion docs/tests/SwapMatchPure.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ contract SwapMatch is NilBase {
//Create a new swap request
SwapRequest memory newSwapRequest = SwapRequest({
initiator: msg.sender,
token: Nil.txnTokens()[0],
token: Nil.txnTokens()[0], // TODO: [PoC] Tokens remove it
secondTokenId: _secondTokenId,
desiredSecondTokenAmount: _desiredSecondTokenAmount,
isMatched: false
Expand Down
2 changes: 1 addition & 1 deletion nil/contracts/solidity/tests/RequestResponseTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ contract RequestResponseTest is NilTokenBase {
require(success, "Request should be successful");
uint ctxValue = abi.decode(context, (uint));
require(ctxValue == uint(11111), "Context value should be the same");
require(Nil.txnTokens().length == 0, "Tokens should be empty");
require(Nil.txnTokens().length == 0, "Tokens should be empty"); // TODO: [PoC] Tokens remove it
}

/**
Expand Down
19 changes: 2 additions & 17 deletions nil/contracts/solidity/tests/TokensTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,7 @@ contract TokensTest is NilTokenBase {
}

function testTransactionTokens(Nil.Token[] memory tokens) public payable {
Nil.Token[] memory transactionTokens = Nil.txnTokens();
require(
transactionTokens.length == tokens.length,
"Tokens length mismatch"
);
for (uint i = 0; i < tokens.length; i++) {
require(
TokenId.unwrap(transactionTokens[i].id) ==
TokenId.unwrap(tokens[i].id),
"Tokens id mismatch"
);
require(
transactionTokens[i].amount == tokens[i].amount,
"Tokens amount mismatch"
);
}
// TODO: [PoC] Tokens fix it
}

function receiveTokens(bool fail) public payable {
Expand Down Expand Up @@ -125,7 +110,7 @@ contract TokensTest is NilTokenBase {
event tokenTxnBalance(uint256 balance);

function checkIncomingToken(TokenId id) public payable {
emit tokenTxnBalance(Nil.txnTokens()[0].amount);
emit tokenTxnBalance(Nil.txnTokens()[0].amount); // TODO: [PoC] Tokens remove it
emit tokenBalance(Nil.tokenBalance(address(this), id));
}

Expand Down
48 changes: 1 addition & 47 deletions nil/internal/vm/precompiled.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ var PrecompiledContractsPrague = map[types.Address]PrecompiledContract{
CheckIsInternalAddress: &checkIsInternal{},
ManageTokenAddress: &manageToken{},
TokenBalanceAddress: &tokenBalance{},
SendTokensAddress: &sendTokenSync{},
TransactionTokensAddress: &getTransactionTokens{},
GetGasPriceAddress: &getGasPrice{},
PoseidonHashAddress: &poseidonHash{},
Expand Down Expand Up @@ -194,7 +193,7 @@ func (a *simple) Run(
_ StateDBReadOnly, /* state */
input []byte,
_ *uint256.Int, /* value */
_ ContractRef, /* caller */
_ ContractRef, /* caller */
) ([]byte, error) {
return a.contract.Run(input)
}
Expand Down Expand Up @@ -823,51 +822,6 @@ func (a *tokenBalance) Run(
return res, nil
}

type sendTokenSync struct{}

var _ ReadWritePrecompiledContract = (*sendTokenSync)(nil)

func (c *sendTokenSync) RequiredGas([]byte, StateDBReadOnly) (uint64, error) {
return 10, nil
}

func (c *sendTokenSync) Run(state StateDB, input []byte, value *uint256.Int, caller ContractRef) ([]byte, error) {
if len(input) < 4 {
return nil, types.NewVmError(types.ErrorPrecompileTooShortCallData)
}

// Unpack arguments, skipping the first 4 bytes (function selector)
args, err := getPrecompiledMethod("precompileSendTokens").Inputs.Unpack(input[4:])
if err != nil {
return nil, types.NewVmVerboseError(types.ErrorAbiUnpackFailed, err.Error())
}
if len(args) != 2 {
return nil, types.NewVmError(types.ErrorPrecompileWrongNumberOfArguments)
}

// Get destination address
addr, ok := args[0].(types.Address)
check.PanicIfNotf(ok, "sendTokenSync failed: addr argument is not an address")

if caller.Address().ShardId() != addr.ShardId() {
return nil, fmt.Errorf("sendTokenSync: %w: %s -> %s",
ErrCrossShardTransaction, caller.Address().ShardId(), addr.ShardId())
}

// Get tokens
tokens, err := extractTokens(args[1])
if err != nil {
return nil, types.NewVmVerboseError(types.ErrorPrecompileInvalidTokenArray, "sendTokenSync")
}

state.SetTokenTransfer(tokens)

res := make([]byte, 32)
res[31] = 1

return res, nil
}

type getTransactionTokens struct{}

var _ ReadOnlyPrecompiledContract = (*getTransactionTokens)(nil)
Expand Down
92 changes: 88 additions & 4 deletions nil/services/rpc/rawapi/internal/local_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (api *localShardApi) CallGetter(
ctx context.Context,
address types.Address,
calldata []byte,
) ([]byte, error){
) ([]byte, error) {
tx, err := api.db.CreateRoTx(ctx)
if err != nil {
return nil, err
Expand All @@ -148,10 +148,10 @@ func (api *localShardApi) CallGetter(
}

extTxn := &types.ExternalTransaction{
FeeCredit: types.GasToValue(types.DefaultMaxGasInBlock.Uint64()),
FeeCredit: types.GasToValue(types.DefaultMaxGasInBlock.Uint64()),
MaxFeePerGas: types.MaxFeePerGasDefault,
To: address,
Data: calldata,
To: address,
Data: calldata,
}

txn := extTxn.ToTransaction()
Expand All @@ -170,6 +170,90 @@ func (api *localShardApi) GetTokens1(
ctx context.Context,
address types.Address,
blockReference rawapitypes.BlockReference,
) (map[types.TokenId]types.Value, error) {
abi, err := contracts.GetAbi(contracts.NameTokenManager)
if err != nil {
return nil, fmt.Errorf("cannot get ABI: %w", err)
}

calldata, err := abi.Pack("getTokens", address)
if err != nil {
return nil, fmt.Errorf("cannot pack calldata: %w", err)
}

tokenManagerAddr := types.ShardAndHexToAddress(address.ShardId(), types.TokenManagerPureAddress)

ret, err := api.CallGetter(ctx, tokenManagerAddr, calldata)
if err != nil {
return nil, fmt.Errorf("failed to call getter: %w", err)
}

var tokens []token
err = abi.UnpackIntoInterface(&tokens, "getTokens", ret)
if err != nil {
return nil, fmt.Errorf("failed to unpack response: %w", err)
}

res := make(map[types.TokenId]types.Value)
for t := range tokens {
res[types.TokenId(tokens[t].Token)] = types.NewValueFromBigMust(tokens[t].Balance)
}
return res, nil
}

func (api *LocalShardApi) CallGetter(
ctx context.Context,
address types.Address,
calldata []byte,
) ([]byte, error) {
tx, err := api.db.CreateRoTx(ctx)
if err != nil {
return nil, err
}
defer tx.Rollback()

block, _, err := db.ReadLastBlock(tx, address.ShardId())
if err != nil {
return nil, fmt.Errorf("failed to read last block: %w", err)
}

cfgAccessor, err := config.NewConfigReader(tx, &block.MainShardHash)
if err != nil {
return nil, fmt.Errorf("failed to create config accessor: %w", err)
}

es, err := execution.NewExecutionState(tx, address.ShardId(), execution.StateParams{
Block: block,
ConfigAccessor: cfgAccessor,
Mode: execution.ModeReadOnly,
})
if err != nil {
return nil, err
}

extTxn := &types.ExternalTransaction{
FeeCredit: types.GasToValue(types.DefaultMaxGasInBlock.Uint64()),
MaxFeePerGas: types.MaxFeePerGasDefault,
To: address,
Data: calldata,
}

txn := extTxn.ToTransaction()

payer := execution.NewDummyPayer()

es.AddInTransaction(txn)
res := es.HandleTransaction(ctx, txn, payer)
if res.Failed() {
return nil, fmt.Errorf("transaction failed: %w", res.GetError())
}
return res.ReturnData, nil
}

func (api *LocalShardApi) GetTokens1(
ctx context.Context,
address types.Address,
blockReference rawapitypes.BlockReference,
) (map[types.TokenId]types.Value, error) {
shardId := address.ShardId()
if shardId != api.shardId() {
Expand Down
Loading