fix send funds from contract
This commit is contained in:
parent
75e88969cb
commit
7b1fc780aa
|
@ -14,11 +14,7 @@ type FakeAppState struct {
|
||||||
|
|
||||||
func (fas *FakeAppState) GetAccount(addr Word256) *Account {
|
func (fas *FakeAppState) GetAccount(addr Word256) *Account {
|
||||||
account := fas.accounts[addr.String()]
|
account := fas.accounts[addr.String()]
|
||||||
if account != nil {
|
|
||||||
return account
|
return account
|
||||||
} else {
|
|
||||||
panic(Fmt("Invalid account addr: %X", addr))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fas *FakeAppState) UpdateAccount(account *Account) {
|
func (fas *FakeAppState) UpdateAccount(account *Account) {
|
||||||
|
|
|
@ -103,10 +103,13 @@ func TestSendCall(t *testing.T) {
|
||||||
account2 := &Account{
|
account2 := &Account{
|
||||||
Address: Uint64ToWord256(101),
|
Address: Uint64ToWord256(101),
|
||||||
}
|
}
|
||||||
fakeAppState.UpdateAccount(account1)
|
account3 := &Account{
|
||||||
fakeAppState.UpdateAccount(account2)
|
Address: Uint64ToWord256(102),
|
||||||
|
}
|
||||||
|
|
||||||
addr := account1.Address.Postfix(20)
|
// account1 will call account2 which will trigger CALL opcode to account3
|
||||||
|
|
||||||
|
addr := account3.Address.Postfix(20)
|
||||||
gas1, gas2 := byte(0x1), byte(0x1)
|
gas1, gas2 := byte(0x1), byte(0x1)
|
||||||
value := byte(0x69)
|
value := byte(0x69)
|
||||||
inOff, inSize := byte(0x0), byte(0x0) // no call data
|
inOff, inSize := byte(0x0), byte(0x0) // no call data
|
||||||
|
@ -121,6 +124,9 @@ func TestSendCall(t *testing.T) {
|
||||||
output, err := ourVm.Call(account1, account2, contractCode, []byte{}, 0, &gas)
|
output, err := ourVm.Call(account1, account2, contractCode, []byte{}, 0, &gas)
|
||||||
fmt.Printf("Output: %v Error: %v\n", output, err)
|
fmt.Printf("Output: %v Error: %v\n", output, err)
|
||||||
fmt.Println("Call took:", time.Since(start))
|
fmt.Println("Call took:", time.Since(start))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
24
vm/vm.go
24
vm/vm.go
|
@ -71,20 +71,18 @@ func (vm *VM) SetFireable(evc events.Fireable) {
|
||||||
// CONTRACT appState is aware of caller and callee, so we can just mutate them.
|
// CONTRACT appState is aware of caller and callee, so we can just mutate them.
|
||||||
// value: To be transferred from caller to callee. Refunded upon error.
|
// value: To be transferred from caller to callee. Refunded upon error.
|
||||||
// gas: Available gas. No refunds for gas.
|
// gas: Available gas. No refunds for gas.
|
||||||
|
// code: May be nil, since the CALL opcode may be used to send value from contracts to accounts
|
||||||
func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
|
func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
|
||||||
|
|
||||||
if len(code) == 0 {
|
|
||||||
panic("Call() requires code")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = transfer(caller, callee, value); err != nil {
|
if err = transfer(caller, callee, value); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exception := ""
|
||||||
|
if len(code) > 0 {
|
||||||
vm.callDepth += 1
|
vm.callDepth += 1
|
||||||
output, err = vm.call(caller, callee, code, input, value, gas)
|
output, err = vm.call(caller, callee, code, input, value, gas)
|
||||||
vm.callDepth -= 1
|
vm.callDepth -= 1
|
||||||
exception := ""
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception = err.Error()
|
exception = err.Error()
|
||||||
err := transfer(callee, caller, value)
|
err := transfer(callee, caller, value)
|
||||||
|
@ -92,6 +90,8 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
panic("Could not return value to caller")
|
panic("Could not return value to caller")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if callDepth is 0 the event is fired from ExecTx (along with the Input event)
|
// if callDepth is 0 the event is fired from ExecTx (along with the Input event)
|
||||||
// otherwise, we fire from here.
|
// otherwise, we fire from here.
|
||||||
if vm.callDepth != 0 && vm.evc != nil {
|
if vm.callDepth != 0 && vm.evc != nil {
|
||||||
|
@ -713,12 +713,24 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(addr)
|
acc := vm.appState.GetAccount(addr)
|
||||||
|
// since CALL is used also for sending funds,
|
||||||
|
// acc may not exist yet. This is an error for
|
||||||
|
// CALLCODE, but not for CALL, though I don't think
|
||||||
|
// ethereum actually cares
|
||||||
|
if op == CALLCODE {
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
}
|
}
|
||||||
if op == CALLCODE {
|
|
||||||
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
||||||
} else {
|
} else {
|
||||||
|
if acc == nil {
|
||||||
|
// if we have not seen the account before, create it
|
||||||
|
// so we can send funds
|
||||||
|
acc = &Account{
|
||||||
|
Address: addr,
|
||||||
|
}
|
||||||
|
vm.appState.UpdateAccount(acc)
|
||||||
|
}
|
||||||
ret, err = vm.Call(callee, acc, acc.Code, args, value, gas)
|
ret, err = vm.Call(callee, acc, acc.Code, args, value, gas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue