Skip to content

Commit 3738970

Browse files
committed
base
1 parent 1671948 commit 3738970

File tree

14 files changed

+327
-36
lines changed

14 files changed

+327
-36
lines changed

nil/internal/contracts/contract.go

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const (
2121
NameNilConfigAbi = "NilConfigAbi"
2222
NameL1BlockInfo = "system/L1BlockInfo"
2323
NameGovernance = "system/Governance"
24+
NameTokenManager = "TokenManager"
2425
)
2526

2627
var (

nil/internal/execution/state.go

+16-23
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
)
3030

3131
const (
32-
TraceBlocksEnabled = false
32+
TraceBlocksEnabled = true
3333
ExternalTransactionVerificationMaxGas = types.Gas(100_000)
3434

3535
ModeReadOnly = "read-only"
@@ -942,28 +942,6 @@ func (es *ExecutionState) AddOutTransaction(
942942

943943
txnHash := txn.Hash()
944944

945-
// In case of bounce transaction, we don't debit token from account
946-
// In case of refund transaction, we don't transfer tokens
947-
if !txn.IsBounce() && !txn.IsRefund() {
948-
acc, err := es.GetAccount(txn.From)
949-
if err != nil {
950-
return nil, err
951-
}
952-
for _, token := range txn.Token {
953-
balance := acc.GetTokenBalance(token.Token)
954-
if balance == nil {
955-
balance = &types.Value{}
956-
}
957-
if balance.Cmp(token.Balance) < 0 {
958-
return nil, fmt.Errorf("%w: %s < %s, token %s",
959-
vm.ErrInsufficientBalance, balance, token.Balance, token.Token)
960-
}
961-
if err := es.SubToken(txn.From, token.Token, token.Balance); err != nil {
962-
return nil, err
963-
}
964-
}
965-
}
966-
967945
es.logger.Trace().
968946
Stringer(logging.FieldTransactionHash, txnHash).
969947
Stringer(logging.FieldTransactionFrom, txn.From).
@@ -1353,6 +1331,8 @@ func (es *ExecutionState) handleExecutionTransaction(
13531331
}
13541332
defer es.resetVm()
13551333

1334+
//es.EnableVmTracing()
1335+
13561336
es.preTxHookCall(transaction)
13571337
defer func() { es.postTxHookCall(transaction, res) }()
13581338

@@ -2029,6 +2009,19 @@ func (es *ExecutionState) postTxHookCall(txn *types.Transaction, txResult *Execu
20292009
}
20302010
}
20312011

2012+
func (es *ExecutionState) EnableVmTracing() {
2013+
es.evm.Config.Tracer = &tracing.Hooks{
2014+
OnOpcode: func(
2015+
pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error,
2016+
) {
2017+
for i, item := range scope.StackData() {
2018+
fmt.Printf(" %d: %s\n", i, item.String())
2019+
}
2020+
fmt.Printf("%04x: %s\n", pc, vm.OpCode(op).String())
2021+
},
2022+
}
2023+
}
2024+
20322025
func VerboseTracingHooks(logger logging.Logger) *tracing.Hooks {
20332026
return &tracing.Hooks{
20342027
OnOpcode: func(

nil/internal/execution/zerostate.go

+17
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ func CreateDefaultZeroStateConfig(mainPublicKey []byte) (*ZeroStateConfig, error
8181
return zeroStateConfig, nil
8282
}
8383

84+
func AddRelayersToZeroStateConfig(zeroStateConfig *ZeroStateConfig, shardsNum int) {
85+
for i := range shardsNum {
86+
zeroStateConfig.Contracts = append(zeroStateConfig.Contracts, &ContractDescr{
87+
Name: fmt.Sprintf("Relayer_%d", i),
88+
Contract: "Relayer",
89+
Address: types.ShardAndHexToAddress(types.ShardId(i), types.RelayerPureAddress),
90+
Value: types.Value0,
91+
})
92+
zeroStateConfig.Contracts = append(zeroStateConfig.Contracts, &ContractDescr{
93+
Name: fmt.Sprintf("TokenManager_%d", i),
94+
Contract: "TokenManager",
95+
Address: types.ShardAndHexToAddress(types.ShardId(i), types.TokenManagerPureAddress),
96+
Value: types.Value0,
97+
})
98+
}
99+
}
100+
84101
func (cfg *ZeroStateConfig) GetValidators() []config.ListValidators {
85102
return cfg.ConfigParams.Validators.Validators
86103
}

nil/internal/types/address.go

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ var (
3232
UsdcFaucetAddress = ShardAndHexToAddress(BaseShardId, "111111111111111111111111111111111115")
3333
L1BlockInfoAddress = ShardAndHexToAddress(MainShardId, "222222222222222222222222222222222222")
3434
GovernanceAddress = ShardAndHexToAddress(MainShardId, "777777777777777777777777777777777777")
35+
RelayerPureAddress = "333333333333333333333333333333333333"
36+
TokenManagerPureAddress = "444444444444444444444444444444444444"
3537
)
3638

3739
func GetTokenName(addr TokenId) string {

nil/internal/vm/precompiled.go

+1
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ func (c *manageToken) RequiredGas([]byte, StateDBReadOnly) (uint64, error) {
832832
}
833833

834834
func (c *manageToken) Run(state StateDB, input []byte, value *uint256.Int, caller ContractRef) ([]byte, error) {
835+
panic("Deprecated")
835836
if len(input) < 4 {
836837
return nil, types.NewVmError(types.ErrorPrecompileTooShortCallData)
837838
}

nil/services/rpc/rawapi/local_account.go

+92-1
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
87
"github.com/NilFoundation/nil/nil/common"
8+
"github.com/NilFoundation/nil/nil/internal/config"
9+
"github.com/NilFoundation/nil/nil/internal/contracts"
910
"github.com/NilFoundation/nil/nil/internal/db"
1011
"github.com/NilFoundation/nil/nil/internal/execution"
1112
"github.com/NilFoundation/nil/nil/internal/mpt"
1213
"github.com/NilFoundation/nil/nil/internal/types"
1314
rawapitypes "github.com/NilFoundation/nil/nil/services/rpc/rawapi/types"
15+
"math/big"
1416
)
1517

1618
var errBlockNotFound = errors.New("block not found")
@@ -75,10 +77,99 @@ func (api *LocalShardApi) GetCode(
7577
return code, nil
7678
}
7779

80+
type token struct {
81+
Token types.Address
82+
Balance *big.Int
83+
}
84+
7885
func (api *LocalShardApi) GetTokens(
7986
ctx context.Context,
8087
address types.Address,
8188
blockReference rawapitypes.BlockReference,
89+
) (map[types.TokenId]types.Value, error) {
90+
abi, err := contracts.GetAbi(contracts.NameTokenManager)
91+
if err != nil {
92+
return nil, fmt.Errorf("cannot get ABI: %w", err)
93+
}
94+
95+
calldata, err := abi.Pack("getTokens", address)
96+
if err != nil {
97+
return nil, fmt.Errorf("cannot pack calldata: %w", err)
98+
}
99+
100+
tokenManagerAddr := types.ShardAndHexToAddress(address.ShardId(), types.TokenManagerPureAddress)
101+
102+
ret, err := api.CallGetter(ctx, tokenManagerAddr, calldata)
103+
if err != nil {
104+
return nil, fmt.Errorf("failed to call getter: %w", err)
105+
}
106+
107+
var tokens []token
108+
err = abi.UnpackIntoInterface(&tokens, "getTokens", ret)
109+
if err != nil {
110+
return nil, fmt.Errorf("failed to unpack response: %w", err)
111+
}
112+
113+
res := make(map[types.TokenId]types.Value)
114+
for t := range tokens {
115+
res[types.TokenId(tokens[t].Token)] = types.NewValueFromBigMust(tokens[t].Balance)
116+
}
117+
return res, nil
118+
}
119+
120+
func (api *LocalShardApi) CallGetter(
121+
ctx context.Context,
122+
address types.Address,
123+
calldata []byte,
124+
) ([]byte, error){
125+
tx, err := api.db.CreateRoTx(ctx)
126+
if err != nil {
127+
return nil, err
128+
}
129+
defer tx.Rollback()
130+
131+
block, _, err := db.ReadLastBlock(tx, address.ShardId())
132+
if err != nil {
133+
return nil, fmt.Errorf("failed to read last block: %w", err)
134+
}
135+
136+
cfgAccessor, err := config.NewConfigReader(tx, &block.MainShardHash)
137+
if err != nil {
138+
return nil, fmt.Errorf("failed to create config accessor: %w", err)
139+
}
140+
141+
es, err := execution.NewExecutionState(tx, address.ShardId(), execution.StateParams{
142+
Block: block,
143+
ConfigAccessor: cfgAccessor,
144+
Mode: execution.ModeReadOnly,
145+
})
146+
if err != nil {
147+
return nil, err
148+
}
149+
150+
extTxn := &types.ExternalTransaction{
151+
FeeCredit: types.GasToValue(types.DefaultMaxGasInBlock.Uint64()),
152+
MaxFeePerGas: types.MaxFeePerGasDefault,
153+
To: address,
154+
Data: calldata,
155+
}
156+
157+
txn := extTxn.ToTransaction()
158+
159+
payer := execution.NewDummyPayer()
160+
161+
es.AddInTransaction(txn)
162+
res := es.HandleTransaction(ctx, txn, payer)
163+
if res.Failed() {
164+
return nil, fmt.Errorf("transaction failed: %w", res.GetError())
165+
}
166+
return res.ReturnData, nil
167+
}
168+
169+
func (api *LocalShardApi) GetTokens1(
170+
ctx context.Context,
171+
address types.Address,
172+
blockReference rawapitypes.BlockReference,
82173
) (map[types.TokenId]types.Value, error) {
83174
shardId := address.ShardId()
84175
if shardId != api.ShardId {

nil/tests/multitoken/multitoken_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ func (s *SuiteMultiTokenRpc) SetupTest() {
107107
HttpUrl: rpc.GetSockPath(s.T()),
108108
ZeroState: zerostateCfg,
109109
RunMode: nilservice.CollatorsOnlyRunMode,
110+
111+
DisableConsensus: true,
110112
})
111113
}
112114

@@ -206,6 +208,7 @@ func (s *SuiteMultiTokenRpc) TestMultiToken() { //nolint
206208
s.Equal(types.NewValueFromUint64(100), tokens[*token1.id])
207209
})
208210
})
211+
return
209212

210213
s.Run("Send from Wallet1 to Wallet2 via asyncCall", func() {
211214
receipt := s.SendTransactionViaSmartAccountNoCheck(
@@ -238,6 +241,7 @@ func (s *SuiteMultiTokenRpc) TestMultiToken() { //nolint
238241
})
239242
})
240243

244+
241245
s.Run("TestDeployWithToken", func() {
242246
tokens := []types.TokenBalance{{Token: *token1.id, Balance: types.NewValueFromUint64(10)}}
243247
contractCode, _ := s.LoadContract(common.GetAbsolutePath("../contracts/increment.sol"), "Incrementer")

nil/tests/rpc_suite.go

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func (s *RpcSuite) Start(cfg *nilservice.Config) {
8787
cfg.ZeroState, err = execution.CreateDefaultZeroStateConfig(execution.MainPublicKey)
8888
s.Require().NoError(err)
8989
}
90+
execution.AddRelayersToZeroStateConfig(cfg.ZeroState, int(s.ShardsNum))
9091

9192
var serviceInterop chan nilservice.ServiceInterop
9293
if cfg.RunMode == nilservice.CollatorsOnlyRunMode {

nil/tests/timeouts_no_race.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ package tests
55
import "time"
66

77
const (
8-
ReceiptWaitTimeout = 15 * time.Second
8+
ReceiptWaitTimeout = 15 * time.Minute
99
ReceiptPollInterval = 250 * time.Millisecond
10-
BlockWaitTimeout = 10 * time.Second
10+
BlockWaitTimeout = 10 * time.Minute
1111
BlockPollInterval = 100 * time.Millisecond
1212
ShardTickWaitTimeout = 30 * time.Second
1313
ShardTickPollInterval = 1 * time.Second
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
library IterableMapping {
5+
// Iterable mapping from address to uint;
6+
struct Map {
7+
address[] keys;
8+
mapping(address => uint256) values;
9+
mapping(address => uint256) indexOf;
10+
mapping(address => bool) inserted;
11+
}
12+
13+
function get(Map storage map, address key) internal view returns (uint256) {
14+
return map.values[key];
15+
}
16+
17+
function getKeyAtIndex(Map storage map, uint256 index) internal view returns (address) {
18+
return map.keys[index];
19+
}
20+
21+
function size(Map storage map) internal view returns (uint256) {
22+
return map.keys.length;
23+
}
24+
25+
function set(Map storage map, address key, uint256 val) internal {
26+
if (map.inserted[key]) {
27+
map.values[key] = val;
28+
} else {
29+
map.inserted[key] = true;
30+
map.values[key] = val;
31+
map.indexOf[key] = map.keys.length;
32+
map.keys.push(key);
33+
}
34+
}
35+
36+
function remove(Map storage map, address key) internal {
37+
if (!map.inserted[key]) {
38+
return;
39+
}
40+
41+
delete map.inserted[key];
42+
delete map.values[key];
43+
44+
uint256 index = map.indexOf[key];
45+
address lastKey = map.keys[map.keys.length - 1];
46+
47+
map.indexOf[lastKey] = index;
48+
delete map.indexOf[key];
49+
50+
map.keys[index] = lastKey;
51+
map.keys.pop();
52+
}
53+
}

smart-contracts/contracts/Nil.sol

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.0;
33

4+
import "./Relayer.sol";
5+
46
// TokenId is a type that represents a unique token identifier.
57
type TokenId is address;
68

@@ -15,7 +17,7 @@ using {
1517

1618
library Nil {
1719
uint private constant SEND_TRANSACTION = 0xfc;
18-
address private constant ASYNC_CALL = address(0xfd);
20+
address public constant ASYNC_CALL = address(0xfd);
1921
address public constant VERIFY_SIGNATURE = address(0xfe);
2022
address public constant IS_INTERNAL_TRANSACTION = address(0xff);
2123
address public constant MANAGE_TOKEN = address(0xd0);
@@ -162,8 +164,25 @@ library Nil {
162164
Token[] memory tokens,
163165
bytes memory callData
164166
) internal {
165-
__Precompile__(ASYNC_CALL).precompileAsyncCall{value: value}(false, forwardKind, dst, refundTo,
166-
bounceTo, feeCredit, tokens, callData);
167+
Relayer(getRelayerAddress()).sendTx(dst, refundTo, feeCredit, forwardKind, value, tokens, callData);
168+
}
169+
170+
function getRelayerAddress() internal view returns (address) {
171+
uint160 addr = uint160(getShardId(address(this))) << (18 * 8);
172+
addr |= uint160(0x333333333333333333333333333333333333);
173+
return address(addr);
174+
}
175+
176+
function getRelayerAddress(uint shardId) internal view returns (address) {
177+
uint160 addr = uint160(shardId) << (18 * 8);
178+
addr |= uint160(0x333333333333333333333333333333333333);
179+
return address(addr);
180+
}
181+
182+
function getTokenManagerAddress() internal view returns (address) {
183+
uint160 addr = uint160(getShardId(address(this))) << (18 * 8);
184+
addr |= uint160(0x444444444444444444444444444444444444);
185+
return address(addr);
167186
}
168187

169188
/**
@@ -514,7 +533,7 @@ abstract contract NilBounceable is NilBase {
514533
// WARNING: User should never use this contract directly.
515534
contract __Precompile__ {
516535
// if mint flag is set to false, token will be burned instead
517-
function precompileManageToken(uint256 amount, bool mint) public returns(bool) {}
536+
function precompileManageToken(uint256 amount, bool mint, TokenId token) public returns(bool) {}
518537
function precompileGetTokenBalance(TokenId id, address addr) public view returns(uint256) {}
519538
function precompileAsyncCall(bool, uint8, address, address, address, uint, Nil.Token[] memory, bytes memory) public payable returns(bool) {}
520539
function precompileAwaitCall(address, uint, bytes memory) public payable returns(bytes memory, bool) {}

0 commit comments

Comments
 (0)