Skip to content

Commit

Permalink
Merge pull request #2938 from onflow/supun/transaction-resource-field…
Browse files Browse the repository at this point in the history
…-move

Fix transaction resource-typed field move
  • Loading branch information
SupunS authored Nov 9, 2023
2 parents a3073c5 + ab5a032 commit 9e1b7dc
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 4 deletions.
8 changes: 4 additions & 4 deletions runtime/interpreter/simplecompositevalue.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/onflow/atree"

"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/runtime/errors"
"github.com/onflow/cadence/runtime/format"
"github.com/onflow/cadence/runtime/sema"
)
Expand Down Expand Up @@ -147,9 +146,10 @@ func (v *SimpleCompositeValue) GetMember(
return nil
}

func (*SimpleCompositeValue) RemoveMember(_ *Interpreter, _ LocationRange, _ string) Value {
// Simple composite values have no removable members (fields / functions)
panic(errors.NewUnreachableError())
func (v *SimpleCompositeValue) RemoveMember(_ *Interpreter, _ LocationRange, name string) Value {
value := v.Fields[name]
delete(v.Fields, name)
return value
}

func (v *SimpleCompositeValue) SetMember(_ *Interpreter, _ LocationRange, name string, value Value) bool {
Expand Down
96 changes: 96 additions & 0 deletions runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9660,3 +9660,99 @@ func TestNestedResourceMoveInDestructor(t *testing.T) {
RequireError(t, err)
require.ErrorAs(t, err, &interpreter.UseBeforeInitializationError{})
}

func TestNestedResourceMoveInTransaction(t *testing.T) {

t.Parallel()

runtime := newTestInterpreterRuntime()

signerAccount := common.MustBytesToAddress([]byte{0x1})

signers := []Address{signerAccount}

accountCodes := map[Location][]byte{}

runtimeInterface := &testRuntimeInterface{
getCode: func(location Location) (bytes []byte, err error) {
return accountCodes[location], nil
},
storage: newTestLedger(nil, nil),
getSigningAccounts: func() ([]Address, error) {
return signers, nil
},
resolveLocation: singleIdentifierLocationResolver(t),
getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
return accountCodes[location], nil
},
updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) {
accountCodes[location] = code
return nil
},
emitEvent: func(event cadence.Event) error {
return nil
},
log: func(s string) {
fmt.Println(s)
},
}

nextTransactionLocation := newTransactionLocationGenerator()

foo := []byte(`
pub contract Foo {
pub resource Vault {}
pub fun createVault(): @Foo.Vault {
return <- create Foo.Vault()
}
}
`)

// Deploy Foo

deployVault := DeploymentTransaction("Foo", foo)
err := runtime.ExecuteTransaction(
Script{
Source: deployVault,
},
Context{
Interface: runtimeInterface,
Location: nextTransactionLocation(),
},
)
require.NoError(t, err)

// Transaction

attackTransaction := []byte(fmt.Sprintf(`
import Foo from %[1]s
transaction {
let vault: @Foo.Vault?
prepare(acc: AuthAccount) {
self.vault <- Foo.createVault()
}
execute {
let vault2 <- self.vault
destroy <- vault2
}
}`,
signerAccount.HexWithPrefix(),
))

err = runtime.ExecuteTransaction(
Script{
Source: attackTransaction,
},
Context{
Interface: runtimeInterface,
Location: nextTransactionLocation(),
},
)

require.NoError(t, err)
}

0 comments on commit 9e1b7dc

Please sign in to comment.