Skip to content

Commit

Permalink
fix sender and receiver are the same (#4703)
Browse files Browse the repository at this point in the history
  • Loading branch information
simlecode authored Jan 12, 2022
1 parent 049c87c commit 35256b9
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 20 deletions.
4 changes: 2 additions & 2 deletions pkg/vm/vmcontext/invocation_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (ctx *invocationContext) invoke() (ret []byte, errcode exitcode.ExitCode) {
// 3. transfer funds carried by the msg
if !ctx.originMsg.Value.Nil() && !ctx.originMsg.Value.IsZero() {
if ctx.msg.From != toIDAddr {
ctx.vm.transfer(ctx.msg.From, toIDAddr, ctx.originMsg.Value)
ctx.vm.transfer(ctx.msg.From, toIDAddr, ctx.originMsg.Value, ctx.vm.NetworkVersion())
}
}

Expand Down Expand Up @@ -588,7 +588,7 @@ func (ctx *invocationContext) DeleteActor(beneficiary address.Address) {
}

// Transfer the executing actor's balance to the beneficiary
ctx.vm.transfer(receiver, beneficiary, receiverActor.Balance)
ctx.vm.transfer(receiver, beneficiary, receiverActor.Balance, ctx.vm.NetworkVersion())
}

if err := ctx.vm.State.DeleteActor(ctx.vm.context, receiver); err != nil {
Expand Down
99 changes: 81 additions & 18 deletions pkg/vm/vmcontext/vmcontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,22 +675,85 @@ func (vm *VM) shouldBurn(ctx context.Context, msg *types.Message, errcode exitco
// WARNING: this Method will panic if the the amount is negative, accounts dont exist, or have inssuficient funds.
//
// Note: this is not idiomatic, it follows the Spec expectations for this Method.
func (vm *VM) transfer(debitFrom address.Address, creditTo address.Address, amount abi.TokenAmount) {
if amount.LessThan(big.Zero()) {
runtime.Abortf(exitcode.SysErrForbidden, "attempt To transfer negative Value %s From %s To %s", amount, debitFrom, creditTo)
}
func (vm *VM) transfer(from address.Address, to address.Address, amount abi.TokenAmount, networkVersion network.Version) {
var fromActor *types.Actor
var fromID, toID address.Address
var err error
var found bool
// switching the order around so that transactions for more than the balance sent to self fail
if networkVersion >= network.Version15 {
if amount.LessThan(big.Zero()) {
runtime.Abortf(exitcode.SysErrForbidden, "attempt To transfer negative Value %s From %s To %s", amount, from, to)
}

// retrieve debit account
fromActor, found, err := vm.State.GetActor(vm.context, debitFrom)
if err != nil {
panic(err)
}
if !found {
panic(fmt.Errorf("unreachable: debit account not found. %s", err))
fromID, err = vm.State.LookupID(from)
if err != nil {
panic(fmt.Errorf("transfer failed when resolving sender address: %s", err))
}

// retrieve sender account
fromActor, found, err = vm.State.GetActor(vm.context, fromID)
if err != nil {
panic(err)
}
if !found {
panic(fmt.Errorf("unreachable: sender account not found. %s", err))
}

// check that account has enough balance for transfer
if fromActor.Balance.LessThan(amount) {
runtime.Abortf(exitcode.SysErrInsufficientFunds, "sender %s insufficient balance %s To transfer %s To %s", amount, fromActor.Balance, from, to)
}

if from == to {
vmlog.Infow("sending to same address: noop", "from/to addr", from)
return
}

toID, err = vm.State.LookupID(to)
if err != nil {
panic(fmt.Errorf("transfer failed when resolving receiver address: %s", err))
}

if fromID == toID {
vmlog.Infow("sending to same actor ID: noop", "from/to actor", fromID)
return
}
} else {
if from == to {
return
}

fromID, err = vm.State.LookupID(from)
if err != nil {
panic(fmt.Errorf("transfer failed when resolving sender address: %s", err))
}

toID, err = vm.State.LookupID(to)
if err != nil {
panic(fmt.Errorf("transfer failed when resolving receiver address: %s", err))
}

if fromID == toID {
return
}

if amount.LessThan(types.NewInt(0)) {
runtime.Abortf(exitcode.SysErrForbidden, "attempt To transfer negative Value %s From %s To %s", amount, from, to)
}

// retrieve sender account
fromActor, found, err = vm.State.GetActor(vm.context, fromID)
if err != nil {
panic(err)
}
if !found {
panic(fmt.Errorf("unreachable: sender account not found. %s", err))
}
}

// retrieve credit account
toActor, found, err := vm.State.GetActor(vm.context, creditTo)
// retrieve receiver account
toActor, found, err := vm.State.GetActor(vm.context, toID)
if err != nil {
panic(err)
}
Expand All @@ -700,18 +763,18 @@ func (vm *VM) transfer(debitFrom address.Address, creditTo address.Address, amou

// check that account has enough balance for transfer
if fromActor.Balance.LessThan(amount) {
runtime.Abortf(exitcode.SysErrInsufficientFunds, "sender %s insufficient balance %s To transfer %s To %s", amount, fromActor.Balance, debitFrom, creditTo)
runtime.Abortf(exitcode.SysErrInsufficientFunds, "sender %s insufficient balance %s To transfer %s To %s", amount, fromActor.Balance, from, to)
}

// debit funds
// deduct funds
fromActor.Balance = big.Sub(fromActor.Balance, amount)
if err := vm.State.SetActor(vm.context, debitFrom, fromActor); err != nil {
if err := vm.State.SetActor(vm.context, from, fromActor); err != nil {
panic(err)
}

// credit funds
// deposit funds
toActor.Balance = big.Add(toActor.Balance, amount)
if err := vm.State.SetActor(vm.context, creditTo, toActor); err != nil {
if err := vm.State.SetActor(vm.context, to, toActor); err != nil {
panic(err)
}
}
Expand Down

0 comments on commit 35256b9

Please sign in to comment.