Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor erc20 around the _spendAllowance function #240

Merged
merged 14 commits into from Apr 29, 2022

Conversation

Amxx
Copy link
Contributor

@Amxx Amxx commented Mar 28, 2022

Fixes #238

@Amxx Amxx marked this pull request as ready for review March 30, 2022 10:25
@koloz193 koloz193 mentioned this pull request Apr 1, 2022
Copy link
Collaborator

@andrew-fleming andrew-fleming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! I left a minor question and comment.

src/openzeppelin/token/erc20/library.cairo Outdated Show resolved Hide resolved
src/openzeppelin/token/erc20/library.cairo Outdated Show resolved Hide resolved
src/openzeppelin/token/erc20/library.cairo Outdated Show resolved Hide resolved
@Amxx
Copy link
Contributor Author

Amxx commented Apr 14, 2022

This should be good for review

Copy link
Collaborator

@andrew-fleming andrew-fleming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent improvements! I left a few comments—the only major request is prefixing all of the library's storage vars which also allows us to remove the proceeding underscores :)

node.json Outdated Show resolved Hide resolved
Comment on lines 32 to 33
func name_() -> (name: felt):
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func name_() -> (name: felt):
end
func ERC20_name() -> (name: felt):
end

We should still prefix all storage variables to prevent clashes with other libs. Another benefit with namespace though is we can omit the ugly proceeding underscore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO storage should not be imported. Contracts using libraries like this one should only rely on functions (including getters and setters) that are in the corresponding namespace.

Would clash happen for storage with the same name that are part of the dependencies but that are not explicitly imported?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO storage should not be imported. Contracts using libraries like this one should only rely on functions (including getters and setters) that are in the corresponding namespace.

This is probably the safer/better design play. I can agree here.

Would clash happen for storage with the same name that are part of the dependencies but that are not explicitly imported?

Yes with the caveat that the compiler will throw an AssertionError if the same-name storage vars differ in any way—including return value name, variable name, and number of keys. Otherwise, the same-name storage vars will have the same storage address and seen/treated as the same storage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would clash happen for storage with the same name that are part of the dependencies but that are not explicitly imported?

Yes with the caveat that the compiler will throw an AssertionError if the same-name storage vars differ in any way—including return value name, variable name, and number of keys. Otherwise, the same-name storage vars will have the same storage address and seen/treated as the same storage.

IMO, this is terrible language design ...

I renamed the storage slots to account for that.

Comment on lines +60 to +63

func constructor{
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since constructor is not protected and does not clash, my only concern is adding confusion to decorated versus undecorated constructors. Overall, I think this works better though—especially with seeing how it looks in the preset contracts. I'm curious what @martriay thinks.

Copy link
Contributor

@martriay martriay Apr 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong opinions, although not sure if it counts as a constructor since it's not initializing a contract but a subset logic. Maybe initializer helps people distinguish between these two but again, no strong opinions.

src/openzeppelin/token/erc20/library.cairo Outdated Show resolved Hide resolved
src/openzeppelin/token/erc20/library.cairo Outdated Show resolved Hide resolved
Copy link
Collaborator

@andrew-fleming andrew-fleming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work on the changes! This looks good to me. I think @martriay should take a look as well.

Copy link
Contributor

@martriay martriay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great additions! We're still lacking documentation but that might be a bit too much for this PR, I think we can merge this.

await signer.send_transaction(account, erc20.contract_address, 'approve', [spender.contract_address, *MAX_UINT256])

# check approval
execution_info_1 = await erc20.allowance(account.contract_address, spender.contract_address).call()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very fond of execution_info_n for these kind of things but I don't have a better suggestion yet

end

let (current_allowance: Uint256) = ERC20_allowances.read(owner, spender)
let (infinite: Uint256) = uint256_not(Uint256(0, 0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_UINT256 would be a great addition to utils/constants.cairo

@martriay martriay merged commit 844e0ec into OpenZeppelin:main Apr 29, 2022
@Amxx Amxx deleted the feature/erc20/spendallowance branch April 29, 2022 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ERC20 transferFrom does reduce allowance if current value is MaxUint
5 participants