github.com/onflow/flow-go@v0.33.17/fvm/evm/stdlib/contract_test.go (about) 1 package stdlib_test 2 3 import ( 4 "encoding/binary" 5 "testing" 6 7 "github.com/ethereum/go-ethereum/crypto" 8 "github.com/onflow/cadence" 9 "github.com/onflow/cadence/encoding/json" 10 "github.com/onflow/cadence/runtime" 11 "github.com/onflow/cadence/runtime/common" 12 "github.com/onflow/cadence/runtime/tests/utils" 13 coreContracts "github.com/onflow/flow-core-contracts/lib/go/contracts" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 17 "github.com/onflow/flow-go/fvm/blueprints" 18 "github.com/onflow/flow-go/fvm/environment" 19 "github.com/onflow/flow-go/fvm/evm/stdlib" 20 . "github.com/onflow/flow-go/fvm/evm/testutils" 21 "github.com/onflow/flow-go/fvm/evm/types" 22 "github.com/onflow/flow-go/model/flow" 23 ) 24 25 type testContractHandler struct { 26 flowTokenAddress common.Address 27 allocateAddress func() types.Address 28 addressIndex uint64 29 accountByAddress func(types.Address, bool) types.Account 30 lastExecutedBlock func() *types.Block 31 run func(tx []byte, coinbase types.Address) 32 } 33 34 func (t *testContractHandler) FlowTokenAddress() common.Address { 35 return t.flowTokenAddress 36 } 37 38 var _ types.ContractHandler = &testContractHandler{} 39 40 func (t *testContractHandler) AllocateAddress() types.Address { 41 if t.allocateAddress == nil { 42 t.addressIndex++ 43 var address types.Address 44 binary.LittleEndian.PutUint64(address[:], t.addressIndex) 45 return address 46 } 47 return t.allocateAddress() 48 } 49 50 func (t *testContractHandler) AccountByAddress(addr types.Address, isAuthorized bool) types.Account { 51 if t.accountByAddress == nil { 52 panic("unexpected AccountByAddress") 53 } 54 return t.accountByAddress(addr, isAuthorized) 55 } 56 57 func (t *testContractHandler) LastExecutedBlock() *types.Block { 58 if t.lastExecutedBlock == nil { 59 panic("unexpected LastExecutedBlock") 60 } 61 return t.lastExecutedBlock() 62 } 63 64 func (t *testContractHandler) Run(tx []byte, coinbase types.Address) { 65 if t.run == nil { 66 panic("unexpected Run") 67 } 68 t.run(tx, coinbase) 69 } 70 71 type testFlowAccount struct { 72 address types.Address 73 balance func() types.Balance 74 transfer func(address types.Address, balance types.Balance) 75 deposit func(vault *types.FLOWTokenVault) 76 withdraw func(balance types.Balance) *types.FLOWTokenVault 77 deploy func(code types.Code, limit types.GasLimit, balance types.Balance) types.Address 78 call func(address types.Address, data types.Data, limit types.GasLimit, balance types.Balance) types.Data 79 } 80 81 var _ types.Account = &testFlowAccount{} 82 83 func (t *testFlowAccount) Address() types.Address { 84 return t.address 85 } 86 87 func (t *testFlowAccount) Balance() types.Balance { 88 if t.balance == nil { 89 return types.Balance(0) 90 } 91 return t.balance() 92 } 93 94 func (t *testFlowAccount) Transfer(address types.Address, balance types.Balance) { 95 if t.transfer == nil { 96 panic("unexpected Transfer") 97 } 98 t.transfer(address, balance) 99 } 100 101 func (t *testFlowAccount) Deposit(vault *types.FLOWTokenVault) { 102 if t.deposit == nil { 103 panic("unexpected Deposit") 104 } 105 t.deposit(vault) 106 } 107 108 func (t *testFlowAccount) Withdraw(balance types.Balance) *types.FLOWTokenVault { 109 if t.withdraw == nil { 110 panic("unexpected Withdraw") 111 } 112 return t.withdraw(balance) 113 } 114 115 func (t *testFlowAccount) Deploy(code types.Code, limit types.GasLimit, balance types.Balance) types.Address { 116 if t.deploy == nil { 117 panic("unexpected Deploy") 118 } 119 return t.deploy(code, limit, balance) 120 } 121 122 func (t *testFlowAccount) Call(address types.Address, data types.Data, limit types.GasLimit, balance types.Balance) types.Data { 123 if t.call == nil { 124 panic("unexpected Call") 125 } 126 return t.call(address, data, limit, balance) 127 } 128 129 func deployContracts( 130 t *testing.T, 131 rt runtime.Runtime, 132 contractsAddress flow.Address, 133 runtimeInterface *TestRuntimeInterface, 134 transactionEnvironment runtime.Environment, 135 nextTransactionLocation func() common.TransactionLocation, 136 evmAbiOnly bool, 137 ) { 138 139 contractsAddressHex := contractsAddress.Hex() 140 141 contracts := []struct { 142 name string 143 code []byte 144 deployTx []byte 145 }{ 146 { 147 name: "FungibleToken", 148 code: coreContracts.FungibleToken(), 149 }, 150 { 151 name: "NonFungibleToken", 152 code: coreContracts.NonFungibleToken(), 153 }, 154 { 155 name: "MetadataViews", 156 code: coreContracts.MetadataViews( 157 contractsAddressHex, 158 contractsAddressHex, 159 ), 160 }, 161 { 162 name: "FungibleTokenMetadataViews", 163 code: coreContracts.FungibleTokenMetadataViews( 164 contractsAddressHex, 165 contractsAddressHex, 166 ), 167 }, 168 { 169 name: "ViewResolver", 170 code: coreContracts.ViewResolver(), 171 }, 172 { 173 name: "FlowToken", 174 code: coreContracts.FlowToken( 175 contractsAddressHex, 176 contractsAddressHex, 177 contractsAddressHex, 178 ), 179 deployTx: []byte(` 180 transaction(name: String, code: String) { 181 prepare(signer: AuthAccount) { 182 signer.contracts.add(name: name, code: code.utf8, signer) 183 } 184 } 185 `), 186 }, 187 { 188 name: stdlib.ContractName, 189 code: stdlib.ContractCode(contractsAddress, evmAbiOnly), 190 }, 191 } 192 193 for _, contract := range contracts { 194 195 deployTx := contract.deployTx 196 if len(deployTx) == 0 { 197 deployTx = blueprints.DeployContractTransactionTemplate 198 } 199 200 err := rt.ExecuteTransaction( 201 runtime.Script{ 202 Source: deployTx, 203 Arguments: EncodeArgs([]cadence.Value{ 204 cadence.String(contract.name), 205 cadence.String(contract.code), 206 }), 207 }, 208 runtime.Context{ 209 Interface: runtimeInterface, 210 Environment: transactionEnvironment, 211 Location: nextTransactionLocation(), 212 }, 213 ) 214 require.NoError(t, err) 215 } 216 217 } 218 219 func newEVMTransactionEnvironment(handler types.ContractHandler, service flow.Address) runtime.Environment { 220 transactionEnvironment := runtime.NewBaseInterpreterEnvironment(runtime.Config{}) 221 222 stdlib.SetupEnvironment( 223 transactionEnvironment, 224 handler, 225 service, 226 ) 227 228 return transactionEnvironment 229 } 230 231 func newEVMScriptEnvironment(handler types.ContractHandler, service flow.Address) runtime.Environment { 232 scriptEnvironment := runtime.NewScriptInterpreterEnvironment(runtime.Config{}) 233 234 stdlib.SetupEnvironment( 235 scriptEnvironment, 236 handler, 237 service, 238 ) 239 240 return scriptEnvironment 241 } 242 243 func TestEVMEncodeABI(t *testing.T) { 244 245 t.Parallel() 246 247 handler := &testContractHandler{} 248 249 contractsAddress := flow.BytesToAddress([]byte{0x1}) 250 251 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 252 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 253 254 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 255 256 script := []byte(` 257 import EVM from 0x1 258 259 access(all) 260 fun main(): [UInt8] { 261 return EVM.encodeABI(["John Doe", UInt64(33), false]) 262 } 263 `) 264 265 accountCodes := map[common.Location][]byte{} 266 var events []cadence.Event 267 268 computation := uint(0) 269 runtimeInterface := &TestRuntimeInterface{ 270 Storage: NewTestLedger(nil, nil), 271 OnGetSigningAccounts: func() ([]runtime.Address, error) { 272 return []runtime.Address{runtime.Address(contractsAddress)}, nil 273 }, 274 OnResolveLocation: SingleIdentifierLocationResolver(t), 275 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 276 accountCodes[location] = code 277 return nil 278 }, 279 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 280 code = accountCodes[location] 281 return code, nil 282 }, 283 OnEmitEvent: func(event cadence.Event) error { 284 events = append(events, event) 285 return nil 286 }, 287 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 288 return json.Decode(nil, b) 289 }, 290 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 291 if compKind == environment.ComputationKindEVMEncodeABI { 292 computation += intensity 293 } 294 return nil 295 }, 296 } 297 298 nextTransactionLocation := NewTransactionLocationGenerator() 299 nextScriptLocation := NewScriptLocationGenerator() 300 301 // Deploy contracts 302 303 deployContracts( 304 t, 305 rt, 306 contractsAddress, 307 runtimeInterface, 308 transactionEnvironment, 309 nextTransactionLocation, 310 true, 311 ) 312 313 // Run script 314 315 result, err := rt.ExecuteScript( 316 runtime.Script{ 317 Source: script, 318 Arguments: [][]byte{}, 319 }, 320 runtime.Context{ 321 Interface: runtimeInterface, 322 Environment: scriptEnvironment, 323 Location: nextScriptLocation(), 324 }, 325 ) 326 require.NoError(t, err) 327 328 abiBytes := []byte{ 329 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 330 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 331 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 332 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 333 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 334 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 335 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 336 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 337 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 338 0x0, 0x8, 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x44, 0x6f, 0x65, 0x0, 0x0, 339 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 340 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 341 } 342 cdcBytes := make([]cadence.Value, 0) 343 for _, bt := range abiBytes { 344 cdcBytes = append(cdcBytes, cadence.UInt8(bt)) 345 } 346 encodedABI := cadence.NewArray( 347 cdcBytes, 348 ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) 349 350 assert.Equal(t, 351 encodedABI, 352 result, 353 ) 354 assert.Equal(t, computation, uint(len(cdcBytes))) 355 } 356 357 func TestEVMEncodeABIComputation(t *testing.T) { 358 359 t.Parallel() 360 361 handler := &testContractHandler{} 362 363 contractsAddress := flow.BytesToAddress([]byte{0x1}) 364 365 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 366 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 367 368 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 369 370 script := []byte(` 371 import EVM from 0x1 372 373 access(all) 374 fun main(): [UInt8] { 375 let address = EVM.EVMAddress( 376 bytes: [ 377 122, 88, 192, 190, 114, 190, 33, 139, 65, 198, 378 8, 183, 254, 124, 91, 182, 48, 115, 108, 113 379 ] 380 ) 381 let arr: [UInt8] = [1, 2, 3, 4, 5] 382 383 return EVM.encodeABI([ 384 "John Doe", 385 UInt64(33), 386 false, 387 address, 388 [arr], 389 ["one", "two", "three"] 390 ]) 391 } 392 `) 393 394 accountCodes := map[common.Location][]byte{} 395 var events []cadence.Event 396 397 computation := uint(0) 398 runtimeInterface := &TestRuntimeInterface{ 399 Storage: NewTestLedger(nil, nil), 400 OnGetSigningAccounts: func() ([]runtime.Address, error) { 401 return []runtime.Address{runtime.Address(contractsAddress)}, nil 402 }, 403 OnResolveLocation: SingleIdentifierLocationResolver(t), 404 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 405 accountCodes[location] = code 406 return nil 407 }, 408 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 409 code = accountCodes[location] 410 return code, nil 411 }, 412 OnEmitEvent: func(event cadence.Event) error { 413 events = append(events, event) 414 return nil 415 }, 416 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 417 return json.Decode(nil, b) 418 }, 419 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 420 if compKind == environment.ComputationKindEVMEncodeABI { 421 computation += intensity 422 } 423 return nil 424 }, 425 } 426 427 nextTransactionLocation := NewTransactionLocationGenerator() 428 nextScriptLocation := NewScriptLocationGenerator() 429 430 // Deploy contracts 431 432 deployContracts( 433 t, 434 rt, 435 contractsAddress, 436 runtimeInterface, 437 transactionEnvironment, 438 nextTransactionLocation, 439 true, 440 ) 441 442 // Run script 443 444 result, err := rt.ExecuteScript( 445 runtime.Script{ 446 Source: script, 447 Arguments: [][]byte{}, 448 }, 449 runtime.Context{ 450 Interface: runtimeInterface, 451 Environment: scriptEnvironment, 452 Location: nextScriptLocation(), 453 }, 454 ) 455 require.NoError(t, err) 456 457 cdcBytes, ok := result.(cadence.Array) 458 require.True(t, ok) 459 // computation & len(cdcBytes.Values) is equal to 832 460 assert.Equal(t, computation, uint(len(cdcBytes.Values))) 461 } 462 463 func TestEVMEncodeABIComputationEmptyDynamicVariables(t *testing.T) { 464 465 t.Parallel() 466 467 handler := &testContractHandler{} 468 469 contractsAddress := flow.BytesToAddress([]byte{0x1}) 470 471 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 472 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 473 474 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 475 476 script := []byte(` 477 import EVM from 0x1 478 479 access(all) 480 fun main(): [UInt8] { 481 return EVM.encodeABI([ 482 "", 483 [[""], [] as [String]], 484 [] as [UInt8], 485 ["", "", ""] 486 ]) 487 } 488 `) 489 490 accountCodes := map[common.Location][]byte{} 491 var events []cadence.Event 492 493 computation := uint(0) 494 runtimeInterface := &TestRuntimeInterface{ 495 Storage: NewTestLedger(nil, nil), 496 OnGetSigningAccounts: func() ([]runtime.Address, error) { 497 return []runtime.Address{runtime.Address(contractsAddress)}, nil 498 }, 499 OnResolveLocation: SingleIdentifierLocationResolver(t), 500 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 501 accountCodes[location] = code 502 return nil 503 }, 504 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 505 code = accountCodes[location] 506 return code, nil 507 }, 508 OnEmitEvent: func(event cadence.Event) error { 509 events = append(events, event) 510 return nil 511 }, 512 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 513 return json.Decode(nil, b) 514 }, 515 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 516 if compKind == environment.ComputationKindEVMEncodeABI { 517 computation += intensity 518 } 519 return nil 520 }, 521 } 522 523 nextTransactionLocation := NewTransactionLocationGenerator() 524 nextScriptLocation := NewScriptLocationGenerator() 525 526 // Deploy contracts 527 528 deployContracts( 529 t, 530 rt, 531 contractsAddress, 532 runtimeInterface, 533 transactionEnvironment, 534 nextTransactionLocation, 535 true, 536 ) 537 538 // Run script 539 540 result, err := rt.ExecuteScript( 541 runtime.Script{ 542 Source: script, 543 Arguments: [][]byte{}, 544 }, 545 runtime.Context{ 546 Interface: runtimeInterface, 547 Environment: scriptEnvironment, 548 Location: nextScriptLocation(), 549 }, 550 ) 551 require.NoError(t, err) 552 553 cdcBytes, ok := result.(cadence.Array) 554 require.True(t, ok) 555 // computation & len(cdcBytes.Values) is equal to 832 556 assert.Equal(t, computation, uint(len(cdcBytes.Values))) 557 } 558 559 func TestEVMEncodeABIComputationDynamicVariablesAboveChunkSize(t *testing.T) { 560 561 t.Parallel() 562 563 handler := &testContractHandler{} 564 565 contractsAddress := flow.BytesToAddress([]byte{0x1}) 566 567 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 568 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 569 570 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 571 572 script := []byte(` 573 import EVM from 0x1 574 575 access(all) 576 fun main(): [UInt8] { 577 let str = "abcdefghijklmnopqrstuvwxyz" 578 let arr: [UInt64] = [ 579 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 580 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 581 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 582 ] 583 584 return EVM.encodeABI([ 585 str, 586 str.concat(str).concat(str), 587 [[str]], 588 arr, 589 [arr], 590 arr.concat(arr).concat(arr) 591 ]) 592 } 593 `) 594 595 accountCodes := map[common.Location][]byte{} 596 var events []cadence.Event 597 598 computation := uint(0) 599 runtimeInterface := &TestRuntimeInterface{ 600 Storage: NewTestLedger(nil, nil), 601 OnGetSigningAccounts: func() ([]runtime.Address, error) { 602 return []runtime.Address{runtime.Address(contractsAddress)}, nil 603 }, 604 OnResolveLocation: SingleIdentifierLocationResolver(t), 605 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 606 accountCodes[location] = code 607 return nil 608 }, 609 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 610 code = accountCodes[location] 611 return code, nil 612 }, 613 OnEmitEvent: func(event cadence.Event) error { 614 events = append(events, event) 615 return nil 616 }, 617 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 618 return json.Decode(nil, b) 619 }, 620 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 621 if compKind == environment.ComputationKindEVMEncodeABI { 622 computation += intensity 623 } 624 return nil 625 }, 626 } 627 628 nextTransactionLocation := NewTransactionLocationGenerator() 629 nextScriptLocation := NewScriptLocationGenerator() 630 631 // Deploy contracts 632 633 deployContracts( 634 t, 635 rt, 636 contractsAddress, 637 runtimeInterface, 638 transactionEnvironment, 639 nextTransactionLocation, 640 true, 641 ) 642 643 // Run script 644 645 result, err := rt.ExecuteScript( 646 runtime.Script{ 647 Source: script, 648 Arguments: [][]byte{}, 649 }, 650 runtime.Context{ 651 Interface: runtimeInterface, 652 Environment: scriptEnvironment, 653 Location: nextScriptLocation(), 654 }, 655 ) 656 require.NoError(t, err) 657 658 cdcBytes, ok := result.(cadence.Array) 659 require.True(t, ok) 660 // computation & len(cdcBytes.Values) is equal to 832 661 assert.Equal(t, computation, uint(len(cdcBytes.Values))) 662 } 663 664 func TestEVMDecodeABI(t *testing.T) { 665 666 t.Parallel() 667 668 handler := &testContractHandler{} 669 670 contractsAddress := flow.BytesToAddress([]byte{0x1}) 671 672 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 673 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 674 675 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 676 677 script := []byte(` 678 import EVM from 0x1 679 680 access(all) 681 fun main(data: [UInt8]): Bool { 682 let types = [Type<String>(), Type<UInt64>(), Type<Bool>()] 683 let values = EVM.decodeABI(types: types, data: data) 684 685 assert(values.length == 3) 686 assert((values[0] as! String) == "John Doe") 687 assert((values[1] as! UInt64) == UInt64(33)) 688 assert((values[2] as! Bool) == false) 689 690 return true 691 } 692 `) 693 694 accountCodes := map[common.Location][]byte{} 695 var events []cadence.Event 696 697 computation := uint(0) 698 runtimeInterface := &TestRuntimeInterface{ 699 Storage: NewTestLedger(nil, nil), 700 OnGetSigningAccounts: func() ([]runtime.Address, error) { 701 return []runtime.Address{runtime.Address(contractsAddress)}, nil 702 }, 703 OnResolveLocation: SingleIdentifierLocationResolver(t), 704 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 705 accountCodes[location] = code 706 return nil 707 }, 708 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 709 code = accountCodes[location] 710 return code, nil 711 }, 712 OnEmitEvent: func(event cadence.Event) error { 713 events = append(events, event) 714 return nil 715 }, 716 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 717 return json.Decode(nil, b) 718 }, 719 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 720 if compKind == environment.ComputationKindEVMDecodeABI { 721 computation += intensity 722 } 723 return nil 724 }, 725 } 726 727 nextTransactionLocation := NewTransactionLocationGenerator() 728 nextScriptLocation := NewScriptLocationGenerator() 729 730 // Deploy contracts 731 732 deployContracts( 733 t, 734 rt, 735 contractsAddress, 736 runtimeInterface, 737 transactionEnvironment, 738 nextTransactionLocation, 739 true, 740 ) 741 742 // Run script 743 abiBytes := []byte{ 744 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 745 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 746 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 747 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 748 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 749 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 750 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 751 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 752 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 753 0x0, 0x8, 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x44, 0x6f, 0x65, 0x0, 0x0, 754 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 755 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 756 } 757 cdcBytes := make([]cadence.Value, 0) 758 for _, bt := range abiBytes { 759 cdcBytes = append(cdcBytes, cadence.UInt8(bt)) 760 } 761 encodedABI := cadence.NewArray( 762 cdcBytes, 763 ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) 764 765 result, err := rt.ExecuteScript( 766 runtime.Script{ 767 Source: script, 768 Arguments: EncodeArgs([]cadence.Value{ 769 encodedABI, 770 }), 771 }, 772 runtime.Context{ 773 Interface: runtimeInterface, 774 Environment: scriptEnvironment, 775 Location: nextScriptLocation(), 776 }, 777 ) 778 require.NoError(t, err) 779 780 assert.Equal(t, cadence.NewBool(true), result) 781 assert.Equal(t, computation, uint(len(cdcBytes))) 782 } 783 784 func TestEVMDecodeABIComputation(t *testing.T) { 785 786 t.Parallel() 787 788 handler := &testContractHandler{} 789 790 contractsAddress := flow.BytesToAddress([]byte{0x1}) 791 792 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 793 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 794 795 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 796 797 script := []byte(` 798 import EVM from 0x1 799 800 access(all) 801 fun main(): [UInt8] { 802 let address = EVM.EVMAddress( 803 bytes: [ 804 122, 88, 192, 190, 114, 190, 33, 139, 65, 198, 805 8, 183, 254, 124, 91, 182, 48, 115, 108, 113 806 ] 807 ) 808 let arr: [UInt8] = [1, 2, 3, 4, 5] 809 810 let data = EVM.encodeABI([ 811 "John Doe", 812 UInt64(33), 813 true, 814 address, 815 [arr], 816 ["one", "two", "three"] 817 ]) 818 819 let types = [ 820 Type<String>(), Type<UInt64>(), Type<Bool>(), Type<EVM.EVMAddress>(), 821 Type<[[UInt8]]>(), Type<[String]>() 822 ] 823 let values = EVM.decodeABI(types: types, data: data) 824 825 return data 826 } 827 `) 828 829 accountCodes := map[common.Location][]byte{} 830 var events []cadence.Event 831 832 computation := uint(0) 833 runtimeInterface := &TestRuntimeInterface{ 834 Storage: NewTestLedger(nil, nil), 835 OnGetSigningAccounts: func() ([]runtime.Address, error) { 836 return []runtime.Address{runtime.Address(contractsAddress)}, nil 837 }, 838 OnResolveLocation: SingleIdentifierLocationResolver(t), 839 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 840 accountCodes[location] = code 841 return nil 842 }, 843 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 844 code = accountCodes[location] 845 return code, nil 846 }, 847 OnEmitEvent: func(event cadence.Event) error { 848 events = append(events, event) 849 return nil 850 }, 851 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 852 return json.Decode(nil, b) 853 }, 854 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 855 if compKind == environment.ComputationKindEVMDecodeABI { 856 computation += intensity 857 } 858 return nil 859 }, 860 } 861 862 nextTransactionLocation := NewTransactionLocationGenerator() 863 nextScriptLocation := NewScriptLocationGenerator() 864 865 // Deploy contracts 866 867 deployContracts( 868 t, 869 rt, 870 contractsAddress, 871 runtimeInterface, 872 transactionEnvironment, 873 nextTransactionLocation, 874 true, 875 ) 876 877 // Run script 878 879 result, err := rt.ExecuteScript( 880 runtime.Script{ 881 Source: script, 882 Arguments: [][]byte{}, 883 }, 884 runtime.Context{ 885 Interface: runtimeInterface, 886 Environment: scriptEnvironment, 887 Location: nextScriptLocation(), 888 }, 889 ) 890 require.NoError(t, err) 891 892 cdcBytes, ok := result.(cadence.Array) 893 require.True(t, ok) 894 // computation & len(cdcBytes.Values) is equal to 832 895 assert.Equal(t, computation, uint(len(cdcBytes.Values))) 896 } 897 898 func TestEVMEncodeDecodeABIRoundtrip(t *testing.T) { 899 900 t.Parallel() 901 902 handler := &testContractHandler{} 903 904 contractsAddress := flow.BytesToAddress([]byte{0x1}) 905 906 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 907 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 908 909 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 910 911 script := []byte(` 912 import EVM from 0x1 913 914 access(all) 915 fun main(): Bool { 916 // Check EVM.EVMAddress encode/decode 917 // bytes for address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71 918 let address = EVM.EVMAddress( 919 bytes: [ 920 122, 88, 192, 190, 114, 190, 33, 139, 65, 198, 921 8, 183, 254, 124, 91, 182, 48, 115, 108, 113 922 ] 923 ) 924 var data = EVM.encodeABI([address]) 925 var values = EVM.decodeABI(types: [Type<EVM.EVMAddress>()], data: data) 926 assert(values.length == 1) 927 assert((values[0] as! EVM.EVMAddress).bytes == address.bytes) 928 929 // Check String encode/decode 930 data = EVM.encodeABI(["John Doe", ""]) 931 values = EVM.decodeABI(types: [Type<String>(), Type<String>()], data: data) 932 assert((values[0] as! String) == "John Doe") 933 assert((values[1] as! String) == "") 934 935 // Check Bool encode/decode 936 data = EVM.encodeABI([true, false]) 937 values = EVM.decodeABI(types: [Type<Bool>(), Type<Bool>()], data: data) 938 assert((values[0] as! Bool) == true) 939 assert((values[1] as! Bool) == false) 940 941 // Check UInt*/Int* encode/decode 942 data = EVM.encodeABI([ 943 UInt8(33), 944 UInt16(33), 945 UInt32(33), 946 UInt64(33), 947 UInt128(33), 948 UInt256(33), 949 Int8(-33), 950 Int16(-33), 951 Int32(-33), 952 Int64(-33), 953 Int128(-33), 954 Int256(-33) 955 ]) 956 values = EVM.decodeABI( 957 types: [ 958 Type<UInt8>(), 959 Type<UInt16>(), 960 Type<UInt32>(), 961 Type<UInt64>(), 962 Type<UInt128>(), 963 Type<UInt256>(), 964 Type<Int8>(), 965 Type<Int16>(), 966 Type<Int32>(), 967 Type<Int64>(), 968 Type<Int128>(), 969 Type<Int256>() 970 ], 971 data: data 972 ) 973 assert((values[0] as! UInt8) == 33) 974 assert((values[1] as! UInt16) == 33) 975 assert((values[2] as! UInt32) == 33) 976 assert((values[3] as! UInt64) == 33) 977 assert((values[4] as! UInt128) == 33) 978 assert((values[5] as! UInt256) == 33) 979 assert((values[6] as! Int8) == -33) 980 assert((values[7] as! Int16) == -33) 981 assert((values[8] as! Int32) == -33) 982 assert((values[9] as! Int64) == -33) 983 assert((values[10] as! Int128) == -33) 984 assert((values[11] as! Int256) == -33) 985 986 // Check variable-size array of leaf types encode/decode 987 data = EVM.encodeABI([ 988 ["one", "two"], 989 [true, false], 990 [5, 10] as [UInt8], 991 [5, 10] as [UInt16], 992 [5, 10] as [UInt32], 993 [5, 10] as [UInt64], 994 [5, 10] as [UInt128], 995 [5, 10] as [UInt256], 996 [-5, -10] as [Int8], 997 [-5, -10] as [Int16], 998 [-5, -10] as [Int32], 999 [-5, -10] as [Int64], 1000 [-5, -10] as [Int128], 1001 [-5, -10] as [Int256], 1002 [address] as [EVM.EVMAddress] 1003 ]) 1004 values = EVM.decodeABI( 1005 types: [ 1006 Type<[String]>(), 1007 Type<[Bool]>(), 1008 Type<[UInt8]>(), 1009 Type<[UInt16]>(), 1010 Type<[UInt32]>(), 1011 Type<[UInt64]>(), 1012 Type<[UInt128]>(), 1013 Type<[UInt256]>(), 1014 Type<[Int8]>(), 1015 Type<[Int16]>(), 1016 Type<[Int32]>(), 1017 Type<[Int64]>(), 1018 Type<[Int128]>(), 1019 Type<[Int256]>(), 1020 Type<[EVM.EVMAddress]>() 1021 ], 1022 data: data 1023 ) 1024 assert((values[0] as! [String]) == ["one", "two"]) 1025 assert((values[1] as! [Bool]) == [true, false]) 1026 assert((values[2] as! [UInt8]) == [5, 10]) 1027 assert((values[3] as! [UInt16]) == [5, 10]) 1028 assert((values[4] as! [UInt32]) == [5, 10]) 1029 assert((values[5] as! [UInt64]) == [5, 10]) 1030 assert((values[6] as! [UInt128]) == [5, 10]) 1031 assert((values[7] as! [UInt256]) == [5, 10]) 1032 assert((values[8] as! [Int8]) == [-5, -10]) 1033 assert((values[9] as! [Int16]) == [-5, -10]) 1034 assert((values[10] as! [Int32]) == [-5, -10]) 1035 assert((values[11] as! [Int64]) == [-5, -10]) 1036 assert((values[12] as! [Int128]) == [-5, -10]) 1037 assert((values[13] as! [Int256]) == [-5, -10]) 1038 assert((values[14] as! [EVM.EVMAddress])[0].bytes == [address][0].bytes) 1039 1040 // Check constant-size array of leaf types encode/decode 1041 data = EVM.encodeABI([ 1042 ["one", "two"] as [String; 2], 1043 [true, false] as [Bool; 2], 1044 [5, 10] as [UInt8; 2], 1045 [5, 10] as [UInt16; 2], 1046 [5, 10] as [UInt32; 2], 1047 [5, 10] as [UInt64; 2], 1048 [5, 10] as [UInt128; 2], 1049 [5, 10] as [UInt256; 2], 1050 [-5, -10] as [Int8; 2], 1051 [-5, -10] as [Int16; 2], 1052 [-5, -10] as [Int32; 2], 1053 [-5, -10] as [Int64; 2], 1054 [-5, -10] as [Int128; 2], 1055 [-5, -10] as [Int256; 2], 1056 [address] as [EVM.EVMAddress; 1] 1057 ]) 1058 values = EVM.decodeABI( 1059 types: [ 1060 Type<[String; 2]>(), 1061 Type<[Bool; 2]>(), 1062 Type<[UInt8; 2]>(), 1063 Type<[UInt16; 2]>(), 1064 Type<[UInt32; 2]>(), 1065 Type<[UInt64; 2]>(), 1066 Type<[UInt128; 2]>(), 1067 Type<[UInt256; 2]>(), 1068 Type<[Int8; 2]>(), 1069 Type<[Int16; 2]>(), 1070 Type<[Int32; 2]>(), 1071 Type<[Int64; 2]>(), 1072 Type<[Int128; 2]>(), 1073 Type<[Int256; 2]>(), 1074 Type<[EVM.EVMAddress; 1]>() 1075 ], 1076 data: data 1077 ) 1078 assert((values[0] as! [String; 2]) == ["one", "two"]) 1079 assert((values[1] as! [Bool; 2]) == [true, false]) 1080 assert((values[2] as! [UInt8; 2]) == [5, 10]) 1081 assert((values[3] as! [UInt16; 2]) == [5, 10]) 1082 assert((values[4] as! [UInt32; 2]) == [5, 10]) 1083 assert((values[5] as! [UInt64; 2]) == [5, 10]) 1084 assert((values[6] as! [UInt128; 2]) == [5, 10]) 1085 assert((values[7] as! [UInt256; 2]) == [5, 10]) 1086 assert((values[8] as! [Int8; 2]) == [-5, -10]) 1087 assert((values[9] as! [Int16; 2]) == [-5, -10]) 1088 assert((values[10] as! [Int32; 2]) == [-5, -10]) 1089 assert((values[11] as! [Int64; 2]) == [-5, -10]) 1090 assert((values[12] as! [Int128; 2]) == [-5, -10]) 1091 assert((values[13] as! [Int256; 2]) == [-5, -10]) 1092 assert((values[14] as! [EVM.EVMAddress; 1])[0].bytes == [address][0].bytes) 1093 1094 // Check partial decoding of encoded data 1095 data = EVM.encodeABI(["Peter", UInt64(9999)]) 1096 values = EVM.decodeABI(types: [Type<String>()], data: data) 1097 assert(values.length == 1) 1098 assert((values[0] as! String) == "Peter") 1099 1100 // Check nested arrays of leaf values 1101 data = EVM.encodeABI([[["Foo", "Bar"], ["Baz", "Qux"]]]) 1102 values = EVM.decodeABI(types: [Type<[[String]]>()], data: data) 1103 assert(values.length == 1) 1104 assert((values[0] as! [[String]]) == [["Foo", "Bar"], ["Baz", "Qux"]]) 1105 1106 return true 1107 } 1108 `) 1109 1110 accountCodes := map[common.Location][]byte{} 1111 var events []cadence.Event 1112 1113 runtimeInterface := &TestRuntimeInterface{ 1114 Storage: NewTestLedger(nil, nil), 1115 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1116 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1117 }, 1118 OnResolveLocation: SingleIdentifierLocationResolver(t), 1119 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1120 accountCodes[location] = code 1121 return nil 1122 }, 1123 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1124 code = accountCodes[location] 1125 return code, nil 1126 }, 1127 OnEmitEvent: func(event cadence.Event) error { 1128 events = append(events, event) 1129 return nil 1130 }, 1131 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1132 return json.Decode(nil, b) 1133 }, 1134 } 1135 1136 nextTransactionLocation := NewTransactionLocationGenerator() 1137 nextScriptLocation := NewScriptLocationGenerator() 1138 1139 // Deploy contracts 1140 1141 deployContracts( 1142 t, 1143 rt, 1144 contractsAddress, 1145 runtimeInterface, 1146 transactionEnvironment, 1147 nextTransactionLocation, 1148 true, 1149 ) 1150 1151 // Run script 1152 1153 result, err := rt.ExecuteScript( 1154 runtime.Script{ 1155 Source: script, 1156 Arguments: [][]byte{}, 1157 }, 1158 runtime.Context{ 1159 Interface: runtimeInterface, 1160 Environment: scriptEnvironment, 1161 Location: nextScriptLocation(), 1162 }, 1163 ) 1164 require.NoError(t, err) 1165 1166 assert.Equal(t, 1167 cadence.Bool(true), 1168 result, 1169 ) 1170 } 1171 1172 func TestEVMEncodeDecodeABIErrors(t *testing.T) { 1173 1174 t.Parallel() 1175 1176 t.Run("encodeABI with unsupported Address type", func(t *testing.T) { 1177 1178 t.Parallel() 1179 1180 handler := &testContractHandler{} 1181 1182 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1183 1184 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1185 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1186 1187 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1188 1189 accountCodes := map[common.Location][]byte{} 1190 var events []cadence.Event 1191 1192 runtimeInterface := &TestRuntimeInterface{ 1193 Storage: NewTestLedger(nil, nil), 1194 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1195 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1196 }, 1197 OnResolveLocation: SingleIdentifierLocationResolver(t), 1198 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1199 accountCodes[location] = code 1200 return nil 1201 }, 1202 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1203 code = accountCodes[location] 1204 return code, nil 1205 }, 1206 OnEmitEvent: func(event cadence.Event) error { 1207 events = append(events, event) 1208 return nil 1209 }, 1210 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1211 return json.Decode(nil, b) 1212 }, 1213 } 1214 1215 nextTransactionLocation := NewTransactionLocationGenerator() 1216 nextScriptLocation := NewScriptLocationGenerator() 1217 1218 // Deploy contracts 1219 1220 deployContracts( 1221 t, 1222 rt, 1223 contractsAddress, 1224 runtimeInterface, 1225 transactionEnvironment, 1226 nextTransactionLocation, 1227 true, 1228 ) 1229 1230 // Run script 1231 1232 script := []byte(` 1233 import EVM from 0x1 1234 1235 access(all) 1236 fun main(): Bool { 1237 let address: Address = 0x045a1763c93006ca 1238 let data = EVM.encodeABI([address]) 1239 1240 return true 1241 } 1242 `) 1243 1244 _, err := rt.ExecuteScript( 1245 runtime.Script{ 1246 Source: script, 1247 Arguments: [][]byte{}, 1248 }, 1249 runtime.Context{ 1250 Interface: runtimeInterface, 1251 Environment: scriptEnvironment, 1252 Location: nextScriptLocation(), 1253 }, 1254 ) 1255 utils.RequireError(t, err) 1256 assert.ErrorContains( 1257 t, 1258 err, 1259 "failed to ABI encode value of type Address", 1260 ) 1261 }) 1262 1263 t.Run("encodeABI with unsupported fixed-point number type", func(t *testing.T) { 1264 1265 t.Parallel() 1266 1267 handler := &testContractHandler{} 1268 1269 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1270 1271 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1272 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1273 1274 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1275 1276 accountCodes := map[common.Location][]byte{} 1277 var events []cadence.Event 1278 1279 runtimeInterface := &TestRuntimeInterface{ 1280 Storage: NewTestLedger(nil, nil), 1281 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1282 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1283 }, 1284 OnResolveLocation: SingleIdentifierLocationResolver(t), 1285 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1286 accountCodes[location] = code 1287 return nil 1288 }, 1289 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1290 code = accountCodes[location] 1291 return code, nil 1292 }, 1293 OnEmitEvent: func(event cadence.Event) error { 1294 events = append(events, event) 1295 return nil 1296 }, 1297 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1298 return json.Decode(nil, b) 1299 }, 1300 } 1301 1302 nextTransactionLocation := NewTransactionLocationGenerator() 1303 nextScriptLocation := NewScriptLocationGenerator() 1304 1305 // Deploy contracts 1306 1307 deployContracts( 1308 t, 1309 rt, 1310 contractsAddress, 1311 runtimeInterface, 1312 transactionEnvironment, 1313 nextTransactionLocation, 1314 true, 1315 ) 1316 1317 // Run script 1318 1319 script := []byte(` 1320 import EVM from 0x1 1321 1322 access(all) 1323 fun main(): Bool { 1324 let data = EVM.encodeABI([0.2]) 1325 1326 return true 1327 } 1328 `) 1329 1330 _, err := rt.ExecuteScript( 1331 runtime.Script{ 1332 Source: script, 1333 Arguments: [][]byte{}, 1334 }, 1335 runtime.Context{ 1336 Interface: runtimeInterface, 1337 Environment: scriptEnvironment, 1338 Location: nextScriptLocation(), 1339 }, 1340 ) 1341 utils.RequireError(t, err) 1342 assert.ErrorContains( 1343 t, 1344 err, 1345 "failed to ABI encode value of type UFix64", 1346 ) 1347 }) 1348 1349 t.Run("encodeABI with unsupported dictionary type", func(t *testing.T) { 1350 1351 t.Parallel() 1352 1353 handler := &testContractHandler{} 1354 1355 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1356 1357 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1358 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1359 1360 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1361 1362 accountCodes := map[common.Location][]byte{} 1363 var events []cadence.Event 1364 1365 runtimeInterface := &TestRuntimeInterface{ 1366 Storage: NewTestLedger(nil, nil), 1367 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1368 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1369 }, 1370 OnResolveLocation: SingleIdentifierLocationResolver(t), 1371 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1372 accountCodes[location] = code 1373 return nil 1374 }, 1375 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1376 code = accountCodes[location] 1377 return code, nil 1378 }, 1379 OnEmitEvent: func(event cadence.Event) error { 1380 events = append(events, event) 1381 return nil 1382 }, 1383 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1384 return json.Decode(nil, b) 1385 }, 1386 } 1387 1388 nextTransactionLocation := NewTransactionLocationGenerator() 1389 nextScriptLocation := NewScriptLocationGenerator() 1390 1391 // Deploy contracts 1392 1393 deployContracts( 1394 t, 1395 rt, 1396 contractsAddress, 1397 runtimeInterface, 1398 transactionEnvironment, 1399 nextTransactionLocation, 1400 true, 1401 ) 1402 1403 // Run script 1404 1405 script := []byte(` 1406 import EVM from 0x1 1407 1408 access(all) 1409 fun main(): Bool { 1410 let dict: {Int: Bool} = {0: false, 1: true} 1411 let data = EVM.encodeABI([dict]) 1412 1413 return true 1414 } 1415 `) 1416 1417 _, err := rt.ExecuteScript( 1418 runtime.Script{ 1419 Source: script, 1420 Arguments: [][]byte{}, 1421 }, 1422 runtime.Context{ 1423 Interface: runtimeInterface, 1424 Environment: scriptEnvironment, 1425 Location: nextScriptLocation(), 1426 }, 1427 ) 1428 utils.RequireError(t, err) 1429 assert.ErrorContains( 1430 t, 1431 err, 1432 "failed to ABI encode value of type {Int: Bool}", 1433 ) 1434 }) 1435 1436 t.Run("encodeABI with unsupported array element type", func(t *testing.T) { 1437 1438 t.Parallel() 1439 1440 handler := &testContractHandler{} 1441 1442 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1443 1444 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1445 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1446 1447 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1448 1449 accountCodes := map[common.Location][]byte{} 1450 var events []cadence.Event 1451 1452 runtimeInterface := &TestRuntimeInterface{ 1453 Storage: NewTestLedger(nil, nil), 1454 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1455 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1456 }, 1457 OnResolveLocation: SingleIdentifierLocationResolver(t), 1458 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1459 accountCodes[location] = code 1460 return nil 1461 }, 1462 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1463 code = accountCodes[location] 1464 return code, nil 1465 }, 1466 OnEmitEvent: func(event cadence.Event) error { 1467 events = append(events, event) 1468 return nil 1469 }, 1470 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1471 return json.Decode(nil, b) 1472 }, 1473 } 1474 1475 nextTransactionLocation := NewTransactionLocationGenerator() 1476 nextScriptLocation := NewScriptLocationGenerator() 1477 1478 // Deploy contracts 1479 1480 deployContracts( 1481 t, 1482 rt, 1483 contractsAddress, 1484 runtimeInterface, 1485 transactionEnvironment, 1486 nextTransactionLocation, 1487 true, 1488 ) 1489 1490 // Run script 1491 1492 script := []byte(` 1493 import EVM from 0x1 1494 1495 access(all) 1496 fun main(): Bool { 1497 let chars: [Character] = ["a", "b", "c"] 1498 let data = EVM.encodeABI([chars]) 1499 1500 return true 1501 } 1502 `) 1503 1504 _, err := rt.ExecuteScript( 1505 runtime.Script{ 1506 Source: script, 1507 Arguments: [][]byte{}, 1508 }, 1509 runtime.Context{ 1510 Interface: runtimeInterface, 1511 Environment: scriptEnvironment, 1512 Location: nextScriptLocation(), 1513 }, 1514 ) 1515 utils.RequireError(t, err) 1516 assert.ErrorContains( 1517 t, 1518 err, 1519 "failed to ABI encode value of type Character", 1520 ) 1521 }) 1522 1523 t.Run("encodeABI with unsupported custom composite type", func(t *testing.T) { 1524 1525 t.Parallel() 1526 1527 handler := &testContractHandler{} 1528 1529 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1530 1531 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1532 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1533 1534 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1535 1536 accountCodes := map[common.Location][]byte{} 1537 var events []cadence.Event 1538 1539 runtimeInterface := &TestRuntimeInterface{ 1540 Storage: NewTestLedger(nil, nil), 1541 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1542 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1543 }, 1544 OnResolveLocation: SingleIdentifierLocationResolver(t), 1545 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1546 accountCodes[location] = code 1547 return nil 1548 }, 1549 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1550 code = accountCodes[location] 1551 return code, nil 1552 }, 1553 OnEmitEvent: func(event cadence.Event) error { 1554 events = append(events, event) 1555 return nil 1556 }, 1557 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1558 return json.Decode(nil, b) 1559 }, 1560 } 1561 1562 nextTransactionLocation := NewTransactionLocationGenerator() 1563 nextScriptLocation := NewScriptLocationGenerator() 1564 1565 // Deploy contracts 1566 1567 deployContracts( 1568 t, 1569 rt, 1570 contractsAddress, 1571 runtimeInterface, 1572 transactionEnvironment, 1573 nextTransactionLocation, 1574 true, 1575 ) 1576 1577 // Run script 1578 1579 script := []byte(` 1580 import EVM from 0x1 1581 1582 access(all) struct Token { 1583 access(all) let id: Int 1584 access(all) var balance: Int 1585 1586 init(id: Int, balance: Int) { 1587 self.id = id 1588 self.balance = balance 1589 } 1590 } 1591 1592 access(all) 1593 fun main(): Bool { 1594 let token = Token(id: 9, balance: 150) 1595 let data = EVM.encodeABI([token]) 1596 1597 return true 1598 } 1599 `) 1600 1601 _, err := rt.ExecuteScript( 1602 runtime.Script{ 1603 Source: script, 1604 Arguments: [][]byte{}, 1605 }, 1606 runtime.Context{ 1607 Interface: runtimeInterface, 1608 Environment: scriptEnvironment, 1609 Location: nextScriptLocation(), 1610 }, 1611 ) 1612 utils.RequireError(t, err) 1613 assert.ErrorContains( 1614 t, 1615 err, 1616 "failed to ABI encode value of type s.0100000000000000000000000000000000000000000000000000000000000000.Token", 1617 ) 1618 }) 1619 1620 t.Run("decodeABI with mismatched type", func(t *testing.T) { 1621 1622 t.Parallel() 1623 1624 handler := &testContractHandler{} 1625 1626 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1627 1628 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1629 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1630 1631 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1632 1633 accountCodes := map[common.Location][]byte{} 1634 var events []cadence.Event 1635 1636 runtimeInterface := &TestRuntimeInterface{ 1637 Storage: NewTestLedger(nil, nil), 1638 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1639 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1640 }, 1641 OnResolveLocation: SingleIdentifierLocationResolver(t), 1642 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1643 accountCodes[location] = code 1644 return nil 1645 }, 1646 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1647 code = accountCodes[location] 1648 return code, nil 1649 }, 1650 OnEmitEvent: func(event cadence.Event) error { 1651 events = append(events, event) 1652 return nil 1653 }, 1654 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1655 return json.Decode(nil, b) 1656 }, 1657 } 1658 1659 nextTransactionLocation := NewTransactionLocationGenerator() 1660 nextScriptLocation := NewScriptLocationGenerator() 1661 1662 // Deploy contracts 1663 1664 deployContracts( 1665 t, 1666 rt, 1667 contractsAddress, 1668 runtimeInterface, 1669 transactionEnvironment, 1670 nextTransactionLocation, 1671 true, 1672 ) 1673 1674 // Run script 1675 1676 script := []byte(` 1677 import EVM from 0x1 1678 1679 access(all) 1680 fun main(): Bool { 1681 let data = EVM.encodeABI(["Peter"]) 1682 let values = EVM.decodeABI(types: [Type<Bool>()], data: data) 1683 1684 return true 1685 } 1686 `) 1687 1688 _, err := rt.ExecuteScript( 1689 runtime.Script{ 1690 Source: script, 1691 Arguments: [][]byte{}, 1692 }, 1693 runtime.Context{ 1694 Interface: runtimeInterface, 1695 Environment: scriptEnvironment, 1696 Location: nextScriptLocation(), 1697 }, 1698 ) 1699 utils.RequireError(t, err) 1700 assert.ErrorContains( 1701 t, 1702 err, 1703 "failed to ABI decode data", 1704 ) 1705 }) 1706 1707 t.Run("decodeABI with surplus of types", func(t *testing.T) { 1708 1709 t.Parallel() 1710 1711 handler := &testContractHandler{} 1712 1713 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1714 1715 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1716 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1717 1718 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1719 1720 accountCodes := map[common.Location][]byte{} 1721 var events []cadence.Event 1722 1723 runtimeInterface := &TestRuntimeInterface{ 1724 Storage: NewTestLedger(nil, nil), 1725 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1726 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1727 }, 1728 OnResolveLocation: SingleIdentifierLocationResolver(t), 1729 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1730 accountCodes[location] = code 1731 return nil 1732 }, 1733 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1734 code = accountCodes[location] 1735 return code, nil 1736 }, 1737 OnEmitEvent: func(event cadence.Event) error { 1738 events = append(events, event) 1739 return nil 1740 }, 1741 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1742 return json.Decode(nil, b) 1743 }, 1744 } 1745 1746 nextTransactionLocation := NewTransactionLocationGenerator() 1747 nextScriptLocation := NewScriptLocationGenerator() 1748 1749 // Deploy contracts 1750 1751 deployContracts( 1752 t, 1753 rt, 1754 contractsAddress, 1755 runtimeInterface, 1756 transactionEnvironment, 1757 nextTransactionLocation, 1758 true, 1759 ) 1760 1761 // Run script 1762 1763 script := []byte(` 1764 import EVM from 0x1 1765 1766 access(all) 1767 fun main(): Bool { 1768 let data = EVM.encodeABI(["Peter"]) 1769 let values = EVM.decodeABI(types: [Type<String>(), Type<Bool>()], data: data) 1770 1771 return true 1772 } 1773 `) 1774 1775 _, err := rt.ExecuteScript( 1776 runtime.Script{ 1777 Source: script, 1778 Arguments: [][]byte{}, 1779 }, 1780 runtime.Context{ 1781 Interface: runtimeInterface, 1782 Environment: scriptEnvironment, 1783 Location: nextScriptLocation(), 1784 }, 1785 ) 1786 utils.RequireError(t, err) 1787 assert.ErrorContains( 1788 t, 1789 err, 1790 "failed to ABI decode data", 1791 ) 1792 }) 1793 1794 t.Run("decodeABI with unsupported fixed-point number type", func(t *testing.T) { 1795 1796 t.Parallel() 1797 1798 handler := &testContractHandler{} 1799 1800 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1801 1802 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1803 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1804 1805 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1806 1807 accountCodes := map[common.Location][]byte{} 1808 var events []cadence.Event 1809 1810 runtimeInterface := &TestRuntimeInterface{ 1811 Storage: NewTestLedger(nil, nil), 1812 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1813 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1814 }, 1815 OnResolveLocation: SingleIdentifierLocationResolver(t), 1816 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1817 accountCodes[location] = code 1818 return nil 1819 }, 1820 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1821 code = accountCodes[location] 1822 return code, nil 1823 }, 1824 OnEmitEvent: func(event cadence.Event) error { 1825 events = append(events, event) 1826 return nil 1827 }, 1828 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1829 return json.Decode(nil, b) 1830 }, 1831 } 1832 1833 nextTransactionLocation := NewTransactionLocationGenerator() 1834 nextScriptLocation := NewScriptLocationGenerator() 1835 1836 // Deploy contracts 1837 1838 deployContracts( 1839 t, 1840 rt, 1841 contractsAddress, 1842 runtimeInterface, 1843 transactionEnvironment, 1844 nextTransactionLocation, 1845 true, 1846 ) 1847 1848 // Run script 1849 1850 script := []byte(` 1851 import EVM from 0x1 1852 1853 access(all) 1854 fun main(): Bool { 1855 let data = EVM.encodeABI(["Peter"]) 1856 let values = EVM.decodeABI(types: [Type<UFix64>()], data: data) 1857 1858 return true 1859 } 1860 `) 1861 1862 _, err := rt.ExecuteScript( 1863 runtime.Script{ 1864 Source: script, 1865 Arguments: [][]byte{}, 1866 }, 1867 runtime.Context{ 1868 Interface: runtimeInterface, 1869 Environment: scriptEnvironment, 1870 Location: nextScriptLocation(), 1871 }, 1872 ) 1873 utils.RequireError(t, err) 1874 assert.ErrorContains( 1875 t, 1876 err, 1877 "failed to ABI decode data with type UFix64", 1878 ) 1879 }) 1880 1881 t.Run("decodeABI with unsupported dictionary type", func(t *testing.T) { 1882 1883 t.Parallel() 1884 1885 handler := &testContractHandler{} 1886 1887 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1888 1889 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1890 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1891 1892 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1893 1894 accountCodes := map[common.Location][]byte{} 1895 var events []cadence.Event 1896 1897 runtimeInterface := &TestRuntimeInterface{ 1898 Storage: NewTestLedger(nil, nil), 1899 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1900 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1901 }, 1902 OnResolveLocation: SingleIdentifierLocationResolver(t), 1903 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1904 accountCodes[location] = code 1905 return nil 1906 }, 1907 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1908 code = accountCodes[location] 1909 return code, nil 1910 }, 1911 OnEmitEvent: func(event cadence.Event) error { 1912 events = append(events, event) 1913 return nil 1914 }, 1915 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 1916 return json.Decode(nil, b) 1917 }, 1918 } 1919 1920 nextTransactionLocation := NewTransactionLocationGenerator() 1921 nextScriptLocation := NewScriptLocationGenerator() 1922 1923 // Deploy contracts 1924 1925 deployContracts( 1926 t, 1927 rt, 1928 contractsAddress, 1929 runtimeInterface, 1930 transactionEnvironment, 1931 nextTransactionLocation, 1932 true, 1933 ) 1934 1935 // Run script 1936 1937 script := []byte(` 1938 import EVM from 0x1 1939 1940 access(all) 1941 fun main(): Bool { 1942 let data = EVM.encodeABI(["Peter"]) 1943 let values = EVM.decodeABI(types: [Type<{Int: Bool}>()], data: data) 1944 1945 return true 1946 } 1947 `) 1948 1949 _, err := rt.ExecuteScript( 1950 runtime.Script{ 1951 Source: script, 1952 Arguments: [][]byte{}, 1953 }, 1954 runtime.Context{ 1955 Interface: runtimeInterface, 1956 Environment: scriptEnvironment, 1957 Location: nextScriptLocation(), 1958 }, 1959 ) 1960 utils.RequireError(t, err) 1961 assert.ErrorContains( 1962 t, 1963 err, 1964 "failed to ABI decode data with type {Int: Bool}", 1965 ) 1966 }) 1967 1968 t.Run("decodeABI with unsupported array element type", func(t *testing.T) { 1969 1970 t.Parallel() 1971 1972 handler := &testContractHandler{} 1973 1974 contractsAddress := flow.BytesToAddress([]byte{0x1}) 1975 1976 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 1977 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 1978 1979 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 1980 1981 accountCodes := map[common.Location][]byte{} 1982 var events []cadence.Event 1983 1984 runtimeInterface := &TestRuntimeInterface{ 1985 Storage: NewTestLedger(nil, nil), 1986 OnGetSigningAccounts: func() ([]runtime.Address, error) { 1987 return []runtime.Address{runtime.Address(contractsAddress)}, nil 1988 }, 1989 OnResolveLocation: SingleIdentifierLocationResolver(t), 1990 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 1991 accountCodes[location] = code 1992 return nil 1993 }, 1994 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 1995 code = accountCodes[location] 1996 return code, nil 1997 }, 1998 OnEmitEvent: func(event cadence.Event) error { 1999 events = append(events, event) 2000 return nil 2001 }, 2002 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2003 return json.Decode(nil, b) 2004 }, 2005 } 2006 2007 nextTransactionLocation := NewTransactionLocationGenerator() 2008 nextScriptLocation := NewScriptLocationGenerator() 2009 2010 // Deploy contracts 2011 2012 deployContracts( 2013 t, 2014 rt, 2015 contractsAddress, 2016 runtimeInterface, 2017 transactionEnvironment, 2018 nextTransactionLocation, 2019 true, 2020 ) 2021 2022 // Run script 2023 2024 script := []byte(` 2025 import EVM from 0x1 2026 2027 access(all) 2028 fun main(): Bool { 2029 let data = EVM.encodeABI(["Peter"]) 2030 let values = EVM.decodeABI(types: [Type<[Character]>()], data: data) 2031 2032 return true 2033 } 2034 `) 2035 2036 _, err := rt.ExecuteScript( 2037 runtime.Script{ 2038 Source: script, 2039 Arguments: [][]byte{}, 2040 }, 2041 runtime.Context{ 2042 Interface: runtimeInterface, 2043 Environment: scriptEnvironment, 2044 Location: nextScriptLocation(), 2045 }, 2046 ) 2047 utils.RequireError(t, err) 2048 assert.ErrorContains( 2049 t, 2050 err, 2051 "failed to ABI decode data with type [Character]", 2052 ) 2053 }) 2054 2055 t.Run("decodeABI with unsupported custom composite type", func(t *testing.T) { 2056 2057 t.Parallel() 2058 2059 handler := &testContractHandler{} 2060 2061 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2062 2063 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2064 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2065 2066 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2067 2068 accountCodes := map[common.Location][]byte{} 2069 var events []cadence.Event 2070 2071 runtimeInterface := &TestRuntimeInterface{ 2072 Storage: NewTestLedger(nil, nil), 2073 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2074 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2075 }, 2076 OnResolveLocation: SingleIdentifierLocationResolver(t), 2077 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2078 accountCodes[location] = code 2079 return nil 2080 }, 2081 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2082 code = accountCodes[location] 2083 return code, nil 2084 }, 2085 OnEmitEvent: func(event cadence.Event) error { 2086 events = append(events, event) 2087 return nil 2088 }, 2089 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2090 return json.Decode(nil, b) 2091 }, 2092 } 2093 2094 nextTransactionLocation := NewTransactionLocationGenerator() 2095 nextScriptLocation := NewScriptLocationGenerator() 2096 2097 // Deploy contracts 2098 2099 deployContracts( 2100 t, 2101 rt, 2102 contractsAddress, 2103 runtimeInterface, 2104 transactionEnvironment, 2105 nextTransactionLocation, 2106 true, 2107 ) 2108 2109 // Run script 2110 2111 script := []byte(` 2112 import EVM from 0x1 2113 2114 access(all) struct Token { 2115 access(all) let id: Int 2116 access(all) var balance: Int 2117 2118 init(id: Int, balance: Int) { 2119 self.id = id 2120 self.balance = balance 2121 } 2122 } 2123 2124 access(all) 2125 fun main(): Bool { 2126 let data = EVM.encodeABI(["Peter"]) 2127 let values = EVM.decodeABI(types: [Type<Token>()], data: data) 2128 2129 return true 2130 } 2131 `) 2132 2133 _, err := rt.ExecuteScript( 2134 runtime.Script{ 2135 Source: script, 2136 Arguments: [][]byte{}, 2137 }, 2138 runtime.Context{ 2139 Interface: runtimeInterface, 2140 Environment: scriptEnvironment, 2141 Location: nextScriptLocation(), 2142 }, 2143 ) 2144 utils.RequireError(t, err) 2145 assert.ErrorContains( 2146 t, 2147 err, 2148 "failed to ABI decode data with type s.0100000000000000000000000000000000000000000000000000000000000000.Token", 2149 ) 2150 }) 2151 } 2152 2153 func TestEVMEncodeABIWithSignature(t *testing.T) { 2154 2155 t.Parallel() 2156 2157 handler := &testContractHandler{} 2158 2159 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2160 2161 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2162 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2163 2164 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2165 2166 script := []byte(` 2167 import EVM from 0x1 2168 2169 access(all) 2170 fun main(): [UInt8] { 2171 // bytes for address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71 2172 let address = EVM.EVMAddress( 2173 bytes: [ 2174 122, 88, 192, 190, 114, 190, 33, 139, 65, 198, 2175 8, 183, 254, 124, 91, 182, 48, 115, 108, 113 2176 ] 2177 ) 2178 2179 return EVM.encodeABIWithSignature( 2180 "withdraw(address,uint256)", 2181 [address, UInt256(250)] 2182 ) 2183 } 2184 `) 2185 2186 accountCodes := map[common.Location][]byte{} 2187 var events []cadence.Event 2188 2189 computation := uint(0) 2190 runtimeInterface := &TestRuntimeInterface{ 2191 Storage: NewTestLedger(nil, nil), 2192 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2193 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2194 }, 2195 OnResolveLocation: SingleIdentifierLocationResolver(t), 2196 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2197 accountCodes[location] = code 2198 return nil 2199 }, 2200 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2201 code = accountCodes[location] 2202 return code, nil 2203 }, 2204 OnEmitEvent: func(event cadence.Event) error { 2205 events = append(events, event) 2206 return nil 2207 }, 2208 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2209 return json.Decode(nil, b) 2210 }, 2211 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 2212 if compKind == environment.ComputationKindEVMEncodeABI { 2213 computation += intensity 2214 } 2215 return nil 2216 }, 2217 OnHash: func( 2218 data []byte, 2219 tag string, 2220 hashAlgorithm runtime.HashAlgorithm, 2221 ) ([]byte, error) { 2222 return crypto.Keccak256(data), nil 2223 }, 2224 } 2225 2226 nextTransactionLocation := NewTransactionLocationGenerator() 2227 nextScriptLocation := NewScriptLocationGenerator() 2228 2229 // Deploy contracts 2230 2231 deployContracts( 2232 t, 2233 rt, 2234 contractsAddress, 2235 runtimeInterface, 2236 transactionEnvironment, 2237 nextTransactionLocation, 2238 true, 2239 ) 2240 2241 // Run script 2242 2243 result, err := rt.ExecuteScript( 2244 runtime.Script{ 2245 Source: script, 2246 Arguments: [][]byte{}, 2247 }, 2248 runtime.Context{ 2249 Interface: runtimeInterface, 2250 Environment: scriptEnvironment, 2251 Location: nextScriptLocation(), 2252 }, 2253 ) 2254 require.NoError(t, err) 2255 2256 abiBytes := []byte{ 2257 0xf3, 0xfe, 0xf3, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2258 0x0, 0x0, 0x0, 0x7a, 0x58, 0xc0, 0xbe, 0x72, 0xbe, 0x21, 0x8b, 0x41, 2259 0xc6, 0x8, 0xb7, 0xfe, 0x7c, 0x5b, 0xb6, 0x30, 0x73, 0x6c, 0x71, 0x0, 2260 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2261 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2262 0x0, 0x0, 0xfa, 2263 } 2264 cdcBytes := make([]cadence.Value, 0) 2265 for _, bt := range abiBytes { 2266 cdcBytes = append(cdcBytes, cadence.UInt8(bt)) 2267 } 2268 encodedABI := cadence.NewArray( 2269 cdcBytes, 2270 ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) 2271 2272 assert.Equal(t, 2273 encodedABI, 2274 result, 2275 ) 2276 // The method ID is a byte array of length 4 2277 assert.Equal(t, computation+4, uint(len(cdcBytes))) 2278 } 2279 2280 func TestEVMDecodeABIWithSignature(t *testing.T) { 2281 2282 t.Parallel() 2283 2284 handler := &testContractHandler{} 2285 2286 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2287 2288 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2289 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2290 2291 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2292 2293 script := []byte(` 2294 import EVM from 0x1 2295 2296 access(all) 2297 fun main(data: [UInt8]): Bool { 2298 let values = EVM.decodeABIWithSignature( 2299 "withdraw(address,uint256)", 2300 types: [Type<EVM.EVMAddress>(), Type<UInt256>()], 2301 data: data 2302 ) 2303 2304 // bytes for address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71 2305 let address = EVM.EVMAddress( 2306 bytes: [ 2307 122, 88, 192, 190, 114, 190, 33, 139, 65, 198, 2308 8, 183, 254, 124, 91, 182, 48, 115, 108, 113 2309 ] 2310 ) 2311 2312 assert(values.length == 2) 2313 assert((values[0] as! EVM.EVMAddress).bytes == address.bytes) 2314 assert((values[1] as! UInt256) == UInt256(250)) 2315 2316 return true 2317 } 2318 `) 2319 2320 accountCodes := map[common.Location][]byte{} 2321 var events []cadence.Event 2322 2323 computation := uint(0) 2324 runtimeInterface := &TestRuntimeInterface{ 2325 Storage: NewTestLedger(nil, nil), 2326 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2327 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2328 }, 2329 OnResolveLocation: SingleIdentifierLocationResolver(t), 2330 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2331 accountCodes[location] = code 2332 return nil 2333 }, 2334 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2335 code = accountCodes[location] 2336 return code, nil 2337 }, 2338 OnEmitEvent: func(event cadence.Event) error { 2339 events = append(events, event) 2340 return nil 2341 }, 2342 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2343 return json.Decode(nil, b) 2344 }, 2345 OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { 2346 if compKind == environment.ComputationKindEVMDecodeABI { 2347 computation += intensity 2348 } 2349 return nil 2350 }, 2351 OnHash: func( 2352 data []byte, 2353 tag string, 2354 hashAlgorithm runtime.HashAlgorithm, 2355 ) ([]byte, error) { 2356 return crypto.Keccak256(data), nil 2357 }, 2358 } 2359 2360 nextTransactionLocation := NewTransactionLocationGenerator() 2361 nextScriptLocation := NewScriptLocationGenerator() 2362 2363 // Deploy contracts 2364 2365 deployContracts( 2366 t, 2367 rt, 2368 contractsAddress, 2369 runtimeInterface, 2370 transactionEnvironment, 2371 nextTransactionLocation, 2372 true, 2373 ) 2374 2375 // Run script 2376 abiBytes := []byte{ 2377 0xf3, 0xfe, 0xf3, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2378 0x0, 0x0, 0x0, 0x7a, 0x58, 0xc0, 0xbe, 0x72, 0xbe, 0x21, 0x8b, 0x41, 2379 0xc6, 0x8, 0xb7, 0xfe, 0x7c, 0x5b, 0xb6, 0x30, 0x73, 0x6c, 0x71, 0x0, 2380 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2381 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2382 0x0, 0x0, 0xfa, 2383 } 2384 cdcBytes := make([]cadence.Value, 0) 2385 for _, bt := range abiBytes { 2386 cdcBytes = append(cdcBytes, cadence.UInt8(bt)) 2387 } 2388 encodedABI := cadence.NewArray( 2389 cdcBytes, 2390 ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) 2391 2392 result, err := rt.ExecuteScript( 2393 runtime.Script{ 2394 Source: script, 2395 Arguments: EncodeArgs([]cadence.Value{ 2396 encodedABI, 2397 }), 2398 }, 2399 runtime.Context{ 2400 Interface: runtimeInterface, 2401 Environment: scriptEnvironment, 2402 Location: nextScriptLocation(), 2403 }, 2404 ) 2405 require.NoError(t, err) 2406 2407 assert.Equal(t, cadence.NewBool(true), result) 2408 // The method ID is a byte array of length 4 2409 assert.Equal(t, computation+4, uint(len(cdcBytes))) 2410 } 2411 2412 func TestEVMDecodeABIWithSignatureMismatch(t *testing.T) { 2413 2414 t.Parallel() 2415 2416 handler := &testContractHandler{} 2417 2418 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2419 2420 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2421 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2422 2423 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2424 2425 script := []byte(` 2426 import EVM from 0x1 2427 2428 access(all) 2429 fun main(data: [UInt8]): Bool { 2430 // The data was encoded for the function "withdraw(address,uint256)", 2431 // but we pass a different function signature 2432 let values = EVM.decodeABIWithSignature( 2433 "deposit(uint256, address)", 2434 types: [Type<UInt256>(), Type<EVM.EVMAddress>()], 2435 data: data 2436 ) 2437 2438 return true 2439 } 2440 `) 2441 2442 accountCodes := map[common.Location][]byte{} 2443 var events []cadence.Event 2444 2445 runtimeInterface := &TestRuntimeInterface{ 2446 Storage: NewTestLedger(nil, nil), 2447 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2448 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2449 }, 2450 OnResolveLocation: SingleIdentifierLocationResolver(t), 2451 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2452 accountCodes[location] = code 2453 return nil 2454 }, 2455 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2456 code = accountCodes[location] 2457 return code, nil 2458 }, 2459 OnEmitEvent: func(event cadence.Event) error { 2460 events = append(events, event) 2461 return nil 2462 }, 2463 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2464 return json.Decode(nil, b) 2465 }, 2466 OnHash: func( 2467 data []byte, 2468 tag string, 2469 hashAlgorithm runtime.HashAlgorithm, 2470 ) ([]byte, error) { 2471 return crypto.Keccak256(data), nil 2472 }, 2473 } 2474 2475 nextTransactionLocation := NewTransactionLocationGenerator() 2476 nextScriptLocation := NewScriptLocationGenerator() 2477 2478 // Deploy contracts 2479 2480 deployContracts( 2481 t, 2482 rt, 2483 contractsAddress, 2484 runtimeInterface, 2485 transactionEnvironment, 2486 nextTransactionLocation, 2487 true, 2488 ) 2489 2490 // Run script 2491 abiBytes := []byte{ 2492 0xf3, 0xfe, 0xf3, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2493 0x0, 0x0, 0x0, 0x7a, 0x58, 0xc0, 0xbe, 0x72, 0xbe, 0x21, 0x8b, 0x41, 2494 0xc6, 0x8, 0xb7, 0xfe, 0x7c, 0x5b, 0xb6, 0x30, 0x73, 0x6c, 0x71, 0x0, 2495 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2496 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 2497 0x0, 0x0, 0xfa, 2498 } 2499 cdcBytes := make([]cadence.Value, 0) 2500 for _, bt := range abiBytes { 2501 cdcBytes = append(cdcBytes, cadence.UInt8(bt)) 2502 } 2503 encodedABI := cadence.NewArray( 2504 cdcBytes, 2505 ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) 2506 2507 _, err := rt.ExecuteScript( 2508 runtime.Script{ 2509 Source: script, 2510 Arguments: EncodeArgs([]cadence.Value{ 2511 encodedABI, 2512 }), 2513 }, 2514 runtime.Context{ 2515 Interface: runtimeInterface, 2516 Environment: scriptEnvironment, 2517 Location: nextScriptLocation(), 2518 }, 2519 ) 2520 require.Error(t, err) 2521 assert.ErrorContains(t, err, "panic: signature mismatch") 2522 } 2523 2524 func TestEVMAddressConstructionAndReturn(t *testing.T) { 2525 2526 t.Parallel() 2527 2528 handler := &testContractHandler{} 2529 2530 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2531 2532 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2533 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2534 2535 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2536 2537 script := []byte(` 2538 import EVM from 0x1 2539 2540 access(all) 2541 fun main(_ bytes: [UInt8; 20]): EVM.EVMAddress { 2542 return EVM.EVMAddress(bytes: bytes) 2543 } 2544 `) 2545 2546 accountCodes := map[common.Location][]byte{} 2547 var events []cadence.Event 2548 2549 runtimeInterface := &TestRuntimeInterface{ 2550 Storage: NewTestLedger(nil, nil), 2551 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2552 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2553 }, 2554 OnResolveLocation: SingleIdentifierLocationResolver(t), 2555 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2556 accountCodes[location] = code 2557 return nil 2558 }, 2559 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2560 code = accountCodes[location] 2561 return code, nil 2562 }, 2563 OnEmitEvent: func(event cadence.Event) error { 2564 events = append(events, event) 2565 return nil 2566 }, 2567 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2568 return json.Decode(nil, b) 2569 }, 2570 } 2571 2572 addressBytesArray := cadence.NewArray([]cadence.Value{ 2573 cadence.UInt8(1), cadence.UInt8(1), 2574 cadence.UInt8(2), cadence.UInt8(2), 2575 cadence.UInt8(3), cadence.UInt8(3), 2576 cadence.UInt8(4), cadence.UInt8(4), 2577 cadence.UInt8(5), cadence.UInt8(5), 2578 cadence.UInt8(6), cadence.UInt8(6), 2579 cadence.UInt8(7), cadence.UInt8(7), 2580 cadence.UInt8(8), cadence.UInt8(8), 2581 cadence.UInt8(9), cadence.UInt8(9), 2582 cadence.UInt8(10), cadence.UInt8(10), 2583 }).WithType(stdlib.EVMAddressBytesCadenceType) 2584 2585 nextTransactionLocation := NewTransactionLocationGenerator() 2586 nextScriptLocation := NewScriptLocationGenerator() 2587 2588 // Deploy contracts 2589 2590 deployContracts( 2591 t, 2592 rt, 2593 contractsAddress, 2594 runtimeInterface, 2595 transactionEnvironment, 2596 nextTransactionLocation, 2597 true, 2598 ) 2599 2600 // Run script 2601 2602 result, err := rt.ExecuteScript( 2603 runtime.Script{ 2604 Source: script, 2605 Arguments: EncodeArgs([]cadence.Value{ 2606 addressBytesArray, 2607 }), 2608 }, 2609 runtime.Context{ 2610 Interface: runtimeInterface, 2611 Environment: scriptEnvironment, 2612 Location: nextScriptLocation(), 2613 }, 2614 ) 2615 require.NoError(t, err) 2616 2617 evmAddressCadenceType := stdlib.NewEVMAddressCadenceType(common.Address(contractsAddress)) 2618 2619 assert.Equal(t, 2620 cadence.Struct{ 2621 StructType: evmAddressCadenceType, 2622 Fields: []cadence.Value{ 2623 addressBytesArray, 2624 }, 2625 }, 2626 result, 2627 ) 2628 } 2629 2630 func TestBalanceConstructionAndReturn(t *testing.T) { 2631 2632 t.Parallel() 2633 2634 handler := &testContractHandler{} 2635 2636 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2637 2638 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2639 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2640 2641 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2642 2643 script := []byte(` 2644 import EVM from 0x1 2645 2646 access(all) 2647 fun main(_ flow: UFix64): EVM.Balance { 2648 return EVM.Balance(flow: flow) 2649 } 2650 `) 2651 2652 accountCodes := map[common.Location][]byte{} 2653 var events []cadence.Event 2654 2655 runtimeInterface := &TestRuntimeInterface{ 2656 Storage: NewTestLedger(nil, nil), 2657 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2658 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2659 }, 2660 OnResolveLocation: SingleIdentifierLocationResolver(t), 2661 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2662 accountCodes[location] = code 2663 return nil 2664 }, 2665 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2666 code = accountCodes[location] 2667 return code, nil 2668 }, 2669 OnEmitEvent: func(event cadence.Event) error { 2670 events = append(events, event) 2671 return nil 2672 }, 2673 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2674 return json.Decode(nil, b) 2675 }, 2676 } 2677 2678 nextTransactionLocation := NewTransactionLocationGenerator() 2679 nextScriptLocation := NewScriptLocationGenerator() 2680 2681 // Deploy contracts 2682 2683 deployContracts( 2684 t, 2685 rt, 2686 contractsAddress, 2687 runtimeInterface, 2688 transactionEnvironment, 2689 nextTransactionLocation, 2690 false, 2691 ) 2692 2693 // Run script 2694 2695 flowValue, err := cadence.NewUFix64FromParts(1, 23000000) 2696 require.NoError(t, err) 2697 2698 result, err := rt.ExecuteScript( 2699 runtime.Script{ 2700 Source: script, 2701 Arguments: EncodeArgs([]cadence.Value{ 2702 flowValue, 2703 }), 2704 }, 2705 runtime.Context{ 2706 Interface: runtimeInterface, 2707 Environment: scriptEnvironment, 2708 Location: nextScriptLocation(), 2709 }, 2710 ) 2711 require.NoError(t, err) 2712 2713 evmBalanceCadenceType := stdlib.NewBalanceCadenceType(common.Address(contractsAddress)) 2714 2715 assert.Equal(t, 2716 cadence.Struct{ 2717 StructType: evmBalanceCadenceType, 2718 Fields: []cadence.Value{ 2719 flowValue, 2720 }, 2721 }, 2722 result, 2723 ) 2724 } 2725 2726 func TestEVMRun(t *testing.T) { 2727 2728 t.Parallel() 2729 2730 evmTx := cadence.NewArray([]cadence.Value{ 2731 cadence.UInt8(1), 2732 cadence.UInt8(2), 2733 cadence.UInt8(3), 2734 }).WithType(stdlib.EVMTransactionBytesCadenceType) 2735 2736 coinbase := cadence.NewArray([]cadence.Value{ 2737 cadence.UInt8(1), cadence.UInt8(1), 2738 cadence.UInt8(2), cadence.UInt8(2), 2739 cadence.UInt8(3), cadence.UInt8(3), 2740 cadence.UInt8(4), cadence.UInt8(4), 2741 cadence.UInt8(5), cadence.UInt8(5), 2742 cadence.UInt8(6), cadence.UInt8(6), 2743 cadence.UInt8(7), cadence.UInt8(7), 2744 cadence.UInt8(8), cadence.UInt8(8), 2745 cadence.UInt8(9), cadence.UInt8(9), 2746 cadence.UInt8(10), cadence.UInt8(10), 2747 }).WithType(stdlib.EVMAddressBytesCadenceType) 2748 2749 runCalled := false 2750 2751 handler := &testContractHandler{ 2752 run: func(tx []byte, coinbase types.Address) { 2753 runCalled = true 2754 2755 assert.Equal(t, []byte{1, 2, 3}, tx) 2756 assert.Equal(t, 2757 types.Address{ 2758 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 2759 }, 2760 coinbase, 2761 ) 2762 2763 }, 2764 } 2765 2766 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2767 2768 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2769 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2770 2771 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2772 2773 script := []byte(` 2774 import EVM from 0x1 2775 2776 access(all) 2777 fun main(tx: [UInt8], coinbaseBytes: [UInt8; 20]) { 2778 let coinbase = EVM.EVMAddress(bytes: coinbaseBytes) 2779 EVM.run(tx: tx, coinbase: coinbase) 2780 } 2781 `) 2782 2783 accountCodes := map[common.Location][]byte{} 2784 var events []cadence.Event 2785 2786 runtimeInterface := &TestRuntimeInterface{ 2787 Storage: NewTestLedger(nil, nil), 2788 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2789 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2790 }, 2791 OnResolveLocation: SingleIdentifierLocationResolver(t), 2792 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2793 accountCodes[location] = code 2794 return nil 2795 }, 2796 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2797 code = accountCodes[location] 2798 return code, nil 2799 }, 2800 OnEmitEvent: func(event cadence.Event) error { 2801 events = append(events, event) 2802 return nil 2803 }, 2804 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2805 return json.Decode(nil, b) 2806 }, 2807 } 2808 2809 nextTransactionLocation := NewTransactionLocationGenerator() 2810 nextScriptLocation := NewScriptLocationGenerator() 2811 2812 // Deploy contracts 2813 2814 deployContracts( 2815 t, 2816 rt, 2817 contractsAddress, 2818 runtimeInterface, 2819 transactionEnvironment, 2820 nextTransactionLocation, 2821 false, 2822 ) 2823 2824 // Run script 2825 2826 _, err := rt.ExecuteScript( 2827 runtime.Script{ 2828 Source: script, 2829 Arguments: EncodeArgs([]cadence.Value{evmTx, coinbase}), 2830 }, 2831 runtime.Context{ 2832 Interface: runtimeInterface, 2833 Environment: scriptEnvironment, 2834 Location: nextScriptLocation(), 2835 }, 2836 ) 2837 require.NoError(t, err) 2838 2839 assert.True(t, runCalled) 2840 } 2841 2842 func TestEVMCreateBridgedAccount(t *testing.T) { 2843 2844 t.Parallel() 2845 2846 handler := &testContractHandler{} 2847 2848 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2849 2850 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2851 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2852 2853 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2854 2855 script := []byte(` 2856 import EVM from 0x1 2857 2858 access(all) 2859 fun main(): [UInt8; 20] { 2860 let bridgedAccount1 <- EVM.createBridgedAccount() 2861 destroy bridgedAccount1 2862 2863 let bridgedAccount2 <- EVM.createBridgedAccount() 2864 let bytes = bridgedAccount2.address().bytes 2865 destroy bridgedAccount2 2866 2867 return bytes 2868 } 2869 `) 2870 2871 accountCodes := map[common.Location][]byte{} 2872 var events []cadence.Event 2873 2874 runtimeInterface := &TestRuntimeInterface{ 2875 Storage: NewTestLedger(nil, nil), 2876 OnGetSigningAccounts: func() ([]runtime.Address, error) { 2877 return []runtime.Address{runtime.Address(contractsAddress)}, nil 2878 }, 2879 OnResolveLocation: SingleIdentifierLocationResolver(t), 2880 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 2881 accountCodes[location] = code 2882 return nil 2883 }, 2884 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 2885 code = accountCodes[location] 2886 return code, nil 2887 }, 2888 OnEmitEvent: func(event cadence.Event) error { 2889 events = append(events, event) 2890 return nil 2891 }, 2892 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 2893 return json.Decode(nil, b) 2894 }, 2895 } 2896 2897 nextTransactionLocation := NewTransactionLocationGenerator() 2898 nextScriptLocation := NewScriptLocationGenerator() 2899 2900 // Deploy contracts 2901 2902 deployContracts( 2903 t, 2904 rt, 2905 contractsAddress, 2906 runtimeInterface, 2907 transactionEnvironment, 2908 nextTransactionLocation, 2909 false, 2910 ) 2911 2912 // Run script 2913 2914 actual, err := rt.ExecuteScript( 2915 runtime.Script{ 2916 Source: script, 2917 }, 2918 runtime.Context{ 2919 Interface: runtimeInterface, 2920 Environment: scriptEnvironment, 2921 Location: nextScriptLocation(), 2922 }, 2923 ) 2924 require.NoError(t, err) 2925 2926 expected := cadence.NewArray([]cadence.Value{ 2927 cadence.UInt8(2), cadence.UInt8(0), 2928 cadence.UInt8(0), cadence.UInt8(0), 2929 cadence.UInt8(0), cadence.UInt8(0), 2930 cadence.UInt8(0), cadence.UInt8(0), 2931 cadence.UInt8(0), cadence.UInt8(0), 2932 cadence.UInt8(0), cadence.UInt8(0), 2933 cadence.UInt8(0), cadence.UInt8(0), 2934 cadence.UInt8(0), cadence.UInt8(0), 2935 cadence.UInt8(0), cadence.UInt8(0), 2936 cadence.UInt8(0), cadence.UInt8(0), 2937 }).WithType(cadence.NewConstantSizedArrayType( 2938 types.AddressLength, 2939 cadence.UInt8Type{}, 2940 )) 2941 2942 require.Equal(t, expected, actual) 2943 } 2944 2945 func TestBridgedAccountCall(t *testing.T) { 2946 2947 t.Parallel() 2948 2949 expectedBalance, err := cadence.NewUFix64FromParts(1, 23000000) 2950 require.NoError(t, err) 2951 2952 handler := &testContractHandler{ 2953 accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account { 2954 assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress) 2955 assert.True(t, isAuthorized) 2956 2957 return &testFlowAccount{ 2958 address: fromAddress, 2959 call: func( 2960 toAddress types.Address, 2961 data types.Data, 2962 limit types.GasLimit, 2963 balance types.Balance, 2964 ) types.Data { 2965 assert.Equal(t, types.Address{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, toAddress) 2966 assert.Equal(t, types.Data{4, 5, 6}, data) 2967 assert.Equal(t, types.GasLimit(9999), limit) 2968 assert.Equal(t, types.Balance(expectedBalance), balance) 2969 2970 return types.Data{3, 1, 4} 2971 }, 2972 } 2973 }, 2974 } 2975 2976 contractsAddress := flow.BytesToAddress([]byte{0x1}) 2977 2978 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 2979 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 2980 2981 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 2982 2983 script := []byte(` 2984 import EVM from 0x1 2985 2986 access(all) 2987 fun main(): [UInt8] { 2988 let bridgedAccount <- EVM.createBridgedAccount() 2989 let response = bridgedAccount.call( 2990 to: EVM.EVMAddress( 2991 bytes: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 2992 ), 2993 data: [4, 5, 6], 2994 gasLimit: 9999, 2995 value: EVM.Balance(flow: 1.23) 2996 ) 2997 destroy bridgedAccount 2998 return response 2999 } 3000 `) 3001 3002 accountCodes := map[common.Location][]byte{} 3003 var events []cadence.Event 3004 3005 runtimeInterface := &TestRuntimeInterface{ 3006 Storage: NewTestLedger(nil, nil), 3007 OnGetSigningAccounts: func() ([]runtime.Address, error) { 3008 return []runtime.Address{runtime.Address(contractsAddress)}, nil 3009 }, 3010 OnResolveLocation: SingleIdentifierLocationResolver(t), 3011 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 3012 accountCodes[location] = code 3013 return nil 3014 }, 3015 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 3016 code = accountCodes[location] 3017 return code, nil 3018 }, 3019 OnEmitEvent: func(event cadence.Event) error { 3020 events = append(events, event) 3021 return nil 3022 }, 3023 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 3024 return json.Decode(nil, b) 3025 }, 3026 } 3027 3028 nextTransactionLocation := NewTransactionLocationGenerator() 3029 nextScriptLocation := NewScriptLocationGenerator() 3030 3031 // Deploy contracts 3032 3033 deployContracts( 3034 t, 3035 rt, 3036 contractsAddress, 3037 runtimeInterface, 3038 transactionEnvironment, 3039 nextTransactionLocation, 3040 false, 3041 ) 3042 3043 // Run script 3044 3045 actual, err := rt.ExecuteScript( 3046 runtime.Script{ 3047 Source: script, 3048 }, 3049 runtime.Context{ 3050 Interface: runtimeInterface, 3051 Environment: scriptEnvironment, 3052 Location: nextScriptLocation(), 3053 }, 3054 ) 3055 require.NoError(t, err) 3056 3057 expected := cadence.NewArray([]cadence.Value{ 3058 cadence.UInt8(3), 3059 cadence.UInt8(1), 3060 cadence.UInt8(4), 3061 }).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type{})) 3062 3063 require.Equal(t, expected, actual) 3064 } 3065 3066 func TestEVMAddressDeposit(t *testing.T) { 3067 3068 t.Parallel() 3069 3070 expectedBalance, err := cadence.NewUFix64FromParts(1, 23000000) 3071 require.NoError(t, err) 3072 3073 var deposited bool 3074 3075 handler := &testContractHandler{ 3076 3077 accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account { 3078 assert.Equal(t, types.Address{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress) 3079 assert.False(t, isAuthorized) 3080 3081 return &testFlowAccount{ 3082 address: fromAddress, 3083 deposit: func(vault *types.FLOWTokenVault) { 3084 deposited = true 3085 assert.Equal( 3086 t, 3087 types.Balance(expectedBalance), 3088 vault.Balance(), 3089 ) 3090 }, 3091 } 3092 }, 3093 } 3094 3095 contractsAddress := flow.BytesToAddress([]byte{0x1}) 3096 3097 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 3098 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 3099 3100 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 3101 3102 script := []byte(` 3103 import EVM from 0x1 3104 import FlowToken from 0x1 3105 3106 access(all) 3107 fun main() { 3108 let admin = getAuthAccount(0x1) 3109 .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)! 3110 let minter <- admin.createNewMinter(allowedAmount: 1.23) 3111 let vault <- minter.mintTokens(amount: 1.23) 3112 destroy minter 3113 3114 let address = EVM.EVMAddress( 3115 bytes: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 3116 ) 3117 address.deposit(from: <-vault) 3118 } 3119 `) 3120 3121 accountCodes := map[common.Location][]byte{} 3122 var events []cadence.Event 3123 3124 runtimeInterface := &TestRuntimeInterface{ 3125 Storage: NewTestLedger(nil, nil), 3126 OnGetSigningAccounts: func() ([]runtime.Address, error) { 3127 return []runtime.Address{runtime.Address(contractsAddress)}, nil 3128 }, 3129 OnResolveLocation: SingleIdentifierLocationResolver(t), 3130 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 3131 accountCodes[location] = code 3132 return nil 3133 }, 3134 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 3135 code = accountCodes[location] 3136 return code, nil 3137 }, 3138 OnEmitEvent: func(event cadence.Event) error { 3139 events = append(events, event) 3140 return nil 3141 }, 3142 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 3143 return json.Decode(nil, b) 3144 }, 3145 } 3146 3147 nextTransactionLocation := NewTransactionLocationGenerator() 3148 nextScriptLocation := NewScriptLocationGenerator() 3149 3150 // Deploy contracts 3151 3152 deployContracts( 3153 t, 3154 rt, 3155 contractsAddress, 3156 runtimeInterface, 3157 transactionEnvironment, 3158 nextTransactionLocation, 3159 false, 3160 ) 3161 3162 // Run script 3163 3164 _, err = rt.ExecuteScript( 3165 runtime.Script{ 3166 Source: script, 3167 }, 3168 runtime.Context{ 3169 Interface: runtimeInterface, 3170 Environment: scriptEnvironment, 3171 Location: nextScriptLocation(), 3172 }, 3173 ) 3174 require.NoError(t, err) 3175 3176 require.True(t, deposited) 3177 } 3178 3179 func TestBridgedAccountWithdraw(t *testing.T) { 3180 3181 t.Parallel() 3182 3183 expectedDepositBalance, err := cadence.NewUFix64FromParts(2, 34000000) 3184 require.NoError(t, err) 3185 3186 expectedWithdrawBalance, err := cadence.NewUFix64FromParts(1, 23000000) 3187 require.NoError(t, err) 3188 3189 var deposited bool 3190 var withdrew bool 3191 3192 contractsAddress := flow.BytesToAddress([]byte{0x1}) 3193 3194 handler := &testContractHandler{ 3195 flowTokenAddress: common.Address(contractsAddress), 3196 accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account { 3197 assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress) 3198 assert.Equal(t, deposited, isAuthorized) 3199 3200 return &testFlowAccount{ 3201 address: fromAddress, 3202 deposit: func(vault *types.FLOWTokenVault) { 3203 deposited = true 3204 assert.Equal(t, 3205 types.Balance(expectedDepositBalance), 3206 vault.Balance(), 3207 ) 3208 }, 3209 withdraw: func(balance types.Balance) *types.FLOWTokenVault { 3210 assert.Equal(t, 3211 types.Balance(expectedWithdrawBalance), 3212 balance, 3213 ) 3214 withdrew = true 3215 return types.NewFlowTokenVault(balance) 3216 }, 3217 } 3218 }, 3219 } 3220 3221 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 3222 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 3223 3224 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 3225 3226 script := []byte(` 3227 import EVM from 0x1 3228 import FlowToken from 0x1 3229 3230 access(all) 3231 fun main(): UFix64 { 3232 let admin = getAuthAccount(0x1) 3233 .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)! 3234 let minter <- admin.createNewMinter(allowedAmount: 2.34) 3235 let vault <- minter.mintTokens(amount: 2.34) 3236 destroy minter 3237 3238 let bridgedAccount <- EVM.createBridgedAccount() 3239 bridgedAccount.address().deposit(from: <-vault) 3240 3241 let vault2 <- bridgedAccount.withdraw(balance: EVM.Balance(flow: 1.23)) 3242 let balance = vault2.balance 3243 destroy bridgedAccount 3244 destroy vault2 3245 3246 return balance 3247 } 3248 `) 3249 3250 accountCodes := map[common.Location][]byte{} 3251 var events []cadence.Event 3252 3253 runtimeInterface := &TestRuntimeInterface{ 3254 Storage: NewTestLedger(nil, nil), 3255 OnGetSigningAccounts: func() ([]runtime.Address, error) { 3256 return []runtime.Address{runtime.Address(contractsAddress)}, nil 3257 }, 3258 OnResolveLocation: SingleIdentifierLocationResolver(t), 3259 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 3260 accountCodes[location] = code 3261 return nil 3262 }, 3263 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 3264 code = accountCodes[location] 3265 return code, nil 3266 }, 3267 OnEmitEvent: func(event cadence.Event) error { 3268 events = append(events, event) 3269 return nil 3270 }, 3271 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 3272 return json.Decode(nil, b) 3273 }, 3274 } 3275 3276 nextTransactionLocation := NewTransactionLocationGenerator() 3277 nextScriptLocation := NewScriptLocationGenerator() 3278 3279 // Deploy contracts 3280 3281 deployContracts( 3282 t, 3283 rt, 3284 contractsAddress, 3285 runtimeInterface, 3286 transactionEnvironment, 3287 nextTransactionLocation, 3288 false, 3289 ) 3290 3291 // Run script 3292 3293 result, err := rt.ExecuteScript( 3294 runtime.Script{ 3295 Source: script, 3296 }, 3297 runtime.Context{ 3298 Interface: runtimeInterface, 3299 Environment: scriptEnvironment, 3300 Location: nextScriptLocation(), 3301 }, 3302 ) 3303 require.NoError(t, err) 3304 3305 assert.True(t, deposited) 3306 assert.True(t, withdrew) 3307 assert.Equal(t, expectedWithdrawBalance, result) 3308 } 3309 3310 func TestBridgedAccountDeploy(t *testing.T) { 3311 3312 t.Parallel() 3313 3314 var deployed bool 3315 3316 contractsAddress := flow.BytesToAddress([]byte{0x1}) 3317 3318 expectedBalance, err := cadence.NewUFix64FromParts(1, 23000000) 3319 require.NoError(t, err) 3320 3321 var handler *testContractHandler 3322 handler = &testContractHandler{ 3323 flowTokenAddress: common.Address(contractsAddress), 3324 accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account { 3325 assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress) 3326 assert.True(t, isAuthorized) 3327 3328 return &testFlowAccount{ 3329 address: fromAddress, 3330 deploy: func(code types.Code, limit types.GasLimit, balance types.Balance) types.Address { 3331 deployed = true 3332 assert.Equal(t, types.Code{4, 5, 6}, code) 3333 assert.Equal(t, types.GasLimit(9999), limit) 3334 assert.Equal(t, types.Balance(expectedBalance), balance) 3335 3336 return handler.AllocateAddress() 3337 }, 3338 } 3339 }, 3340 } 3341 3342 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 3343 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 3344 3345 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 3346 3347 script := []byte(` 3348 import EVM from 0x1 3349 import FlowToken from 0x1 3350 3351 access(all) 3352 fun main(): [UInt8; 20] { 3353 let bridgedAccount <- EVM.createBridgedAccount() 3354 let address = bridgedAccount.deploy( 3355 code: [4, 5, 6], 3356 gasLimit: 9999, 3357 value: EVM.Balance(flow: 1.23) 3358 ) 3359 destroy bridgedAccount 3360 return address.bytes 3361 } 3362 `) 3363 3364 accountCodes := map[common.Location][]byte{} 3365 var events []cadence.Event 3366 3367 runtimeInterface := &TestRuntimeInterface{ 3368 Storage: NewTestLedger(nil, nil), 3369 OnGetSigningAccounts: func() ([]runtime.Address, error) { 3370 return []runtime.Address{runtime.Address(contractsAddress)}, nil 3371 }, 3372 OnResolveLocation: SingleIdentifierLocationResolver(t), 3373 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 3374 accountCodes[location] = code 3375 return nil 3376 }, 3377 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 3378 code = accountCodes[location] 3379 return code, nil 3380 }, 3381 OnEmitEvent: func(event cadence.Event) error { 3382 events = append(events, event) 3383 return nil 3384 }, 3385 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 3386 return json.Decode(nil, b) 3387 }, 3388 } 3389 3390 nextTransactionLocation := NewTransactionLocationGenerator() 3391 nextScriptLocation := NewScriptLocationGenerator() 3392 3393 // Deploy contracts 3394 3395 deployContracts( 3396 t, 3397 rt, 3398 contractsAddress, 3399 runtimeInterface, 3400 transactionEnvironment, 3401 nextTransactionLocation, 3402 false, 3403 ) 3404 3405 // Run script 3406 3407 actual, err := rt.ExecuteScript( 3408 runtime.Script{ 3409 Source: script, 3410 }, 3411 runtime.Context{ 3412 Interface: runtimeInterface, 3413 Environment: scriptEnvironment, 3414 Location: nextScriptLocation(), 3415 }, 3416 ) 3417 require.NoError(t, err) 3418 3419 expected := cadence.NewArray([]cadence.Value{ 3420 cadence.UInt8(2), cadence.UInt8(0), 3421 cadence.UInt8(0), cadence.UInt8(0), 3422 cadence.UInt8(0), cadence.UInt8(0), 3423 cadence.UInt8(0), cadence.UInt8(0), 3424 cadence.UInt8(0), cadence.UInt8(0), 3425 cadence.UInt8(0), cadence.UInt8(0), 3426 cadence.UInt8(0), cadence.UInt8(0), 3427 cadence.UInt8(0), cadence.UInt8(0), 3428 cadence.UInt8(0), cadence.UInt8(0), 3429 cadence.UInt8(0), cadence.UInt8(0), 3430 }).WithType(cadence.NewConstantSizedArrayType( 3431 types.AddressLength, 3432 cadence.UInt8Type{}, 3433 )) 3434 3435 require.Equal(t, expected, actual) 3436 3437 require.True(t, deployed) 3438 } 3439 3440 func TestEVMAccountBalance(t *testing.T) { 3441 3442 t.Parallel() 3443 3444 contractsAddress := flow.BytesToAddress([]byte{0x1}) 3445 3446 expectedBalanceValue, err := cadence.NewUFix64FromParts(1, 1337000) 3447 expectedBalance := cadence. 3448 NewStruct([]cadence.Value{expectedBalanceValue}). 3449 WithType(stdlib.NewBalanceCadenceType(common.Address(contractsAddress))) 3450 3451 require.NoError(t, err) 3452 3453 handler := &testContractHandler{ 3454 flowTokenAddress: common.Address(contractsAddress), 3455 accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account { 3456 assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress) 3457 assert.False(t, isAuthorized) 3458 3459 return &testFlowAccount{ 3460 address: fromAddress, 3461 balance: func() types.Balance { 3462 return types.Balance(expectedBalanceValue) 3463 }, 3464 } 3465 }, 3466 } 3467 3468 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 3469 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 3470 3471 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 3472 3473 script := []byte(` 3474 import EVM from 0x1 3475 3476 access(all) 3477 fun main(): EVM.Balance { 3478 let bridgedAccount <- EVM.createBridgedAccount() 3479 let balance = bridgedAccount.balance() 3480 destroy bridgedAccount 3481 return balance 3482 } 3483 `) 3484 3485 accountCodes := map[common.Location][]byte{} 3486 var events []cadence.Event 3487 3488 runtimeInterface := &TestRuntimeInterface{ 3489 Storage: NewTestLedger(nil, nil), 3490 OnGetSigningAccounts: func() ([]runtime.Address, error) { 3491 return []runtime.Address{runtime.Address(contractsAddress)}, nil 3492 }, 3493 OnResolveLocation: SingleIdentifierLocationResolver(t), 3494 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 3495 accountCodes[location] = code 3496 return nil 3497 }, 3498 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 3499 code = accountCodes[location] 3500 return code, nil 3501 }, 3502 OnEmitEvent: func(event cadence.Event) error { 3503 events = append(events, event) 3504 return nil 3505 }, 3506 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 3507 return json.Decode(nil, b) 3508 }, 3509 } 3510 3511 nextTransactionLocation := NewTransactionLocationGenerator() 3512 nextScriptLocation := NewScriptLocationGenerator() 3513 3514 // Deploy contracts 3515 3516 deployContracts( 3517 t, 3518 rt, 3519 contractsAddress, 3520 runtimeInterface, 3521 transactionEnvironment, 3522 nextTransactionLocation, 3523 false, 3524 ) 3525 3526 // Run script 3527 3528 actual, err := rt.ExecuteScript( 3529 runtime.Script{ 3530 Source: script, 3531 }, 3532 runtime.Context{ 3533 Interface: runtimeInterface, 3534 Environment: scriptEnvironment, 3535 Location: nextScriptLocation(), 3536 }, 3537 ) 3538 require.NoError(t, err) 3539 3540 require.NoError(t, err) 3541 require.Equal(t, expectedBalance, actual) 3542 } 3543 3544 func TestEVMAccountBalanceForABIOnlyContract(t *testing.T) { 3545 3546 t.Parallel() 3547 3548 contractsAddress := flow.BytesToAddress([]byte{0x1}) 3549 3550 expectedBalanceValue, err := cadence.NewUFix64FromParts(1, 1337000) 3551 require.NoError(t, err) 3552 3553 handler := &testContractHandler{ 3554 flowTokenAddress: common.Address(contractsAddress), 3555 accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account { 3556 assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress) 3557 assert.False(t, isAuthorized) 3558 3559 return &testFlowAccount{ 3560 address: fromAddress, 3561 balance: func() types.Balance { 3562 return types.Balance(expectedBalanceValue) 3563 }, 3564 } 3565 }, 3566 } 3567 3568 transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) 3569 scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) 3570 3571 rt := runtime.NewInterpreterRuntime(runtime.Config{}) 3572 3573 script := []byte(` 3574 import EVM from 0x1 3575 3576 access(all) 3577 fun main(): EVM.Balance { 3578 let bridgedAccount <- EVM.createBridgedAccount() 3579 let balance = bridgedAccount.balance() 3580 destroy bridgedAccount 3581 return balance 3582 } 3583 `) 3584 3585 accountCodes := map[common.Location][]byte{} 3586 var events []cadence.Event 3587 3588 runtimeInterface := &TestRuntimeInterface{ 3589 Storage: NewTestLedger(nil, nil), 3590 OnGetSigningAccounts: func() ([]runtime.Address, error) { 3591 return []runtime.Address{runtime.Address(contractsAddress)}, nil 3592 }, 3593 OnResolveLocation: SingleIdentifierLocationResolver(t), 3594 OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { 3595 accountCodes[location] = code 3596 return nil 3597 }, 3598 OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { 3599 code = accountCodes[location] 3600 return code, nil 3601 }, 3602 OnEmitEvent: func(event cadence.Event) error { 3603 events = append(events, event) 3604 return nil 3605 }, 3606 OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { 3607 return json.Decode(nil, b) 3608 }, 3609 } 3610 3611 nextTransactionLocation := NewTransactionLocationGenerator() 3612 nextScriptLocation := NewScriptLocationGenerator() 3613 3614 // Deploy contracts 3615 3616 deployContracts( 3617 t, 3618 rt, 3619 contractsAddress, 3620 runtimeInterface, 3621 transactionEnvironment, 3622 nextTransactionLocation, 3623 true, 3624 ) 3625 3626 // Run script 3627 3628 _, err = rt.ExecuteScript( 3629 runtime.Script{ 3630 Source: script, 3631 }, 3632 runtime.Context{ 3633 Interface: runtimeInterface, 3634 Environment: scriptEnvironment, 3635 Location: nextScriptLocation(), 3636 }, 3637 ) 3638 require.Error(t, err) 3639 3640 assert.ErrorContains( 3641 t, 3642 err, 3643 "error: cannot find type in this scope: `EVM.Balance`", 3644 ) 3645 assert.ErrorContains( 3646 t, 3647 err, 3648 "error: value of type `EVM` has no member `createBridgedAccount`", 3649 ) 3650 }