-
Notifications
You must be signed in to change notification settings - Fork 852
Merge Transfer and TransferWithGas gadget #1777
Changes from 19 commits
11be6ee
2811228
7f73a7f
45e19c6
f62b1cc
b919f09
0241779
618f033
37c3fd1
f82c3a7
79d2c3f
52e80c4
0ee4aa4
e3e1b1c
56ccc66
7a13f05
598ad11
0522b5c
77cfbcb
990afe1
7449289
f8773e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -559,13 +559,13 @@ impl<'a> CircuitInputStateRef<'a> { | |
/// balance by `value`. If `fee` is existing (not None), also need to push 1 | ||
/// non-reversible [`AccountOp`] to update `sender` balance by `fee`. | ||
#[allow(clippy::too_many_arguments)] | ||
pub fn transfer_with_fee( | ||
pub fn transfer( | ||
&mut self, | ||
step: &mut ExecStep, | ||
sender: Address, | ||
receiver: Address, | ||
receiver_exists: bool, | ||
must_create: bool, | ||
opcode_is_create: bool, | ||
value: Word, | ||
fee: Option<Word>, | ||
) -> Result<(), Error> { | ||
|
@@ -608,68 +608,29 @@ impl<'a> CircuitInputStateRef<'a> { | |
sender_balance_prev, | ||
sender_balance | ||
); | ||
// If receiver doesn't exist, create it | ||
if !receiver_exists && (!value.is_zero() || must_create) { | ||
|
||
if !value.is_zero() { | ||
self.push_op_reversible( | ||
step, | ||
AccountOp { | ||
address: receiver, | ||
field: AccountField::CodeHash, | ||
value: CodeDB::empty_code_hash().to_word(), | ||
value_prev: Word::zero(), | ||
address: sender, | ||
field: AccountField::Balance, | ||
value: sender_balance, | ||
value_prev: sender_balance_prev, | ||
}, | ||
)?; | ||
} | ||
if value.is_zero() { | ||
// Skip transfer if value == 0 | ||
return Ok(()); | ||
} | ||
|
||
self.push_op_reversible( | ||
step, | ||
AccountOp { | ||
address: sender, | ||
field: AccountField::Balance, | ||
value: sender_balance, | ||
value_prev: sender_balance_prev, | ||
}, | ||
)?; | ||
|
||
let (_found, receiver_account) = self.sdb.get_account(&receiver); | ||
let receiver_balance_prev = receiver_account.balance; | ||
let receiver_balance = receiver_account.balance + value; | ||
self.push_op_reversible( | ||
self.transfer_to( | ||
step, | ||
AccountOp { | ||
address: receiver, | ||
field: AccountField::Balance, | ||
value: receiver_balance, | ||
value_prev: receiver_balance_prev, | ||
}, | ||
)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Same functionality with `transfer_with_fee` but with `fee` set zero. | ||
pub fn transfer( | ||
&mut self, | ||
step: &mut ExecStep, | ||
sender: Address, | ||
receiver: Address, | ||
receiver_exists: bool, | ||
must_create: bool, | ||
value: Word, | ||
) -> Result<(), Error> { | ||
self.transfer_with_fee( | ||
step, | ||
sender, | ||
receiver, | ||
receiver_exists, | ||
must_create, | ||
opcode_is_create, | ||
value, | ||
None, | ||
) | ||
true, | ||
)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Transfer to an address. Create an account if it is not existed before. | ||
|
@@ -678,12 +639,11 @@ impl<'a> CircuitInputStateRef<'a> { | |
step: &mut ExecStep, | ||
receiver: Address, | ||
receiver_exists: bool, | ||
must_create: bool, | ||
opcode_is_create: bool, | ||
value: Word, | ||
reversible: bool, | ||
) -> Result<(), Error> { | ||
// If receiver doesn't exist, create it | ||
if (!receiver_exists && !value.is_zero()) || must_create { | ||
if !receiver_exists && (!value.is_zero() || opcode_is_create) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This condition slips through the old PR that fixes all creation conditions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have to think carefully about this condition. I would love input from reviewers.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From geth impl., an account which doesn't exist will be created only when transfer value is non-zero. But, no matter this account exsists or not, it'll be created again in CREATE/2 opcode. You can see createAccount is called in create and then will find this
in createObject The conclusion is the original condition is correct. In your fix, the account won't be re-created if the receiver exists. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the naming of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this is correct and it matches our behavior.
This is incorrect. Three lines above your quoted createAccount locates a nonzero nonce and non-empty hash check that early exits the function and returns an The EIP-1014: Skinny CREATE2 also states "if nonce or code (of the create2 destination address) is nonzero, then the create-operation fails." So for this PR, the conclusion is that a CREATEX opcode does not guarantee an overwrite of an account. But you might wonder, why the create opcode only checks non empty code hash and non zero nonce. What about storage root and balance? Can we have an account that has code="" and nonce=0, but storage root !=0 or balance !=0? The tl;dr is we can't, for non-trivial reason. I fell into a rabbit hole of a historical study and how the EIP was defined. Fortunately, Gary wrote the best summary of this issue. See ethereum/go-ethereum#28666. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for the confusion. Maybe we could put the link ethereum/go-ethereum#28666 in our comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added to the comment in the constraint part, which might be the place people will check more frequently 77cfbcb. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
My opinion for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I missed the renaming part before. I fixed the renaming here 7449289 |
||
self.account_write( | ||
step, | ||
receiver, | ||
|
Uh oh!
There was an error while loading. Please reload this page.