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 {
|
||||
account := fas.accounts[addr.String()]
|
||||
if account != nil {
|
||||
return account
|
||||
} else {
|
||||
panic(Fmt("Invalid account addr: %X", addr))
|
||||
}
|
||||
return account
|
||||
}
|
||||
|
||||
func (fas *FakeAppState) UpdateAccount(account *Account) {
|
||||
|
|
|
@ -103,10 +103,13 @@ func TestSendCall(t *testing.T) {
|
|||
account2 := &Account{
|
||||
Address: Uint64ToWord256(101),
|
||||
}
|
||||
fakeAppState.UpdateAccount(account1)
|
||||
fakeAppState.UpdateAccount(account2)
|
||||
account3 := &Account{
|
||||
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)
|
||||
value := byte(0x69)
|
||||
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)
|
||||
fmt.Printf("Output: %v Error: %v\n", output, err)
|
||||
fmt.Println("Call took:", time.Since(start))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
40
vm/vm.go
40
vm/vm.go
|
@ -71,27 +71,27 @@ func (vm *VM) SetFireable(evc events.Fireable) {
|
|||
// 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.
|
||||
// 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) {
|
||||
|
||||
if len(code) == 0 {
|
||||
panic("Call() requires code")
|
||||
}
|
||||
|
||||
if err = transfer(caller, callee, value); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
vm.callDepth += 1
|
||||
output, err = vm.call(caller, callee, code, input, value, gas)
|
||||
vm.callDepth -= 1
|
||||
exception := ""
|
||||
if err != nil {
|
||||
exception = err.Error()
|
||||
err := transfer(callee, caller, value)
|
||||
if len(code) > 0 {
|
||||
vm.callDepth += 1
|
||||
output, err = vm.call(caller, callee, code, input, value, gas)
|
||||
vm.callDepth -= 1
|
||||
if err != nil {
|
||||
panic("Could not return value to caller")
|
||||
exception = err.Error()
|
||||
err := transfer(callee, caller, value)
|
||||
if err != nil {
|
||||
panic("Could not return value to caller")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if callDepth is 0 the event is fired from ExecTx (along with the Input event)
|
||||
// otherwise, we fire from here.
|
||||
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)
|
||||
}
|
||||
acc := vm.appState.GetAccount(addr)
|
||||
if acc == nil {
|
||||
return nil, firstErr(err, ErrUnknownAddress)
|
||||
}
|
||||
// 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 {
|
||||
return nil, firstErr(err, ErrUnknownAddress)
|
||||
}
|
||||
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue