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

♻️ Make Base64 Module-Friendly #222

Merged
merged 2 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ AccessControlTest:testSupportsInterfaceInvalidInterfaceId() (gas: 8378)
AccessControlTest:testSupportsInterfaceInvalidInterfaceIdGasCost() (gas: 9211)
AccessControlTest:testSupportsInterfaceSuccess() (gas: 9527)
AccessControlTest:testSupportsInterfaceSuccessGasCost() (gas: 9167)
Base64Test:testDataLengthMismatch() (gas: 16034)
Base64Test:testDecodeEmptyString() (gas: 7914)
Base64Test:testDecodeSafeUrl() (gas: 337923)
Base64Test:testDecodeSentence() (gas: 853899)
Base64Test:testDecodeSingleCharacter() (gas: 159523)
Base64Test:testDecodeWithDoublePadding() (gas: 235836)
Base64Test:testDecodeWithNoPadding() (gas: 186431)
Base64Test:testDecodeWithSinglePadding() (gas: 197205)
Base64Test:testEncodeEmptyString() (gas: 9100)
Base64Test:testEncodeSafeUrl() (gas: 83941)
Base64Test:testEncodeSentence() (gas: 112247)
Base64Test:testEncodeSingleCharacter() (gas: 65823)
Base64Test:testEncodeWithDoublePadding() (gas: 71636)
Base64Test:testEncodeWithNoPadding() (gas: 70361)
Base64Test:testEncodeWithSinglePadding() (gas: 71739)
Base64Test:testDataLengthMismatch() (gas: 111100)
Base64Test:testDecodeEmptyString() (gas: 103102)
Base64Test:testDecodeSafeUrl() (gas: 403600)
Base64Test:testDecodeSentence() (gas: 922077)
Base64Test:testDecodeSingleCharacter() (gas: 225069)
Base64Test:testDecodeWithDoublePadding() (gas: 301746)
Base64Test:testDecodeWithNoPadding() (gas: 252387)
Base64Test:testDecodeWithSinglePadding() (gas: 263115)
Base64Test:testEncodeEmptyString() (gas: 166208)
Base64Test:testEncodeSafeUrl() (gas: 194347)
Base64Test:testEncodeSentence() (gas: 224643)
Base64Test:testEncodeSingleCharacter() (gas: 175035)
Base64Test:testEncodeWithDoublePadding() (gas: 181246)
Base64Test:testEncodeWithNoPadding() (gas: 179971)
Base64Test:testEncodeWithSinglePadding() (gas: 181349)
BatchDistributorInvariants:invariantNoEtherBalance() (runs: 256, calls: 3840, reverts: 3825)
BatchDistributorInvariants:invariantNoTokenBalance() (runs: 256, calls: 3840, reverts: 3825)
BatchDistributorTest:testDistributeEtherMultipleAddressesSuccess() (gas: 153468)
Expand Down Expand Up @@ -658,13 +658,13 @@ SignatureCheckerTest:testFuzzEOAWithInvalidSignature(bytes,string) (runs: 257,
SignatureCheckerTest:testFuzzEOAWithInvalidSigner(string,string) (runs: 257, μ: 22170, ~: 22231)
SignatureCheckerTest:testFuzzEOAWithValidSignature(string,string) (runs: 257, μ: 21289, ~: 21350)
SignatureCheckerTest:testInitialSetup() (gas: 8315)
TimelockControllerInvariants:statefulFuzzExecutedLessThanOrEqualToScheduled() (runs: 256, calls: 3840, reverts: 1247)
TimelockControllerInvariants:statefulFuzzExecutedProposalCancellation() (runs: 256, calls: 3840, reverts: 1288)
TimelockControllerInvariants:statefulFuzzExecutingCancelledProposal() (runs: 256, calls: 3840, reverts: 1234)
TimelockControllerInvariants:statefulFuzzExecutingNotReadyProposal() (runs: 256, calls: 3840, reverts: 1227)
TimelockControllerInvariants:statefulFuzzOnceProposalExecution() (runs: 256, calls: 3840, reverts: 1224)
TimelockControllerInvariants:statefulFuzzProposalsExecutedMatchCount() (runs: 256, calls: 3840, reverts: 1247)
TimelockControllerInvariants:statefulFuzzSumOfProposals() (runs: 256, calls: 3840, reverts: 1247)
TimelockControllerInvariants:statefulFuzzExecutedLessThanOrEqualToScheduled() (runs: 256, calls: 3840, reverts: 1230)
TimelockControllerInvariants:statefulFuzzExecutedProposalCancellation() (runs: 256, calls: 3840, reverts: 1285)
TimelockControllerInvariants:statefulFuzzExecutingCancelledProposal() (runs: 256, calls: 3840, reverts: 1250)
TimelockControllerInvariants:statefulFuzzExecutingNotReadyProposal() (runs: 256, calls: 3840, reverts: 1257)
TimelockControllerInvariants:statefulFuzzOnceProposalExecution() (runs: 256, calls: 3840, reverts: 1278)
TimelockControllerInvariants:statefulFuzzProposalsExecutedMatchCount() (runs: 256, calls: 3840, reverts: 1230)
TimelockControllerInvariants:statefulFuzzSumOfProposals() (runs: 256, calls: 3840, reverts: 1230)
TimelockControllerTest:testAdminCannotBatchExecute() (gas: 750799)
TimelockControllerTest:testAdminCannotBatchSchedule() (gas: 748585)
TimelockControllerTest:testAdminCannotCancel() (gas: 13521)
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
- [`Ownable2Step`](https://github.com/pcaversaccio/snekmate/blob/v0.1.0/src/snekmate/auth/Ownable2Step.vy): Make `Ownable2Step` module-friendly. ([#219](https://github.com/pcaversaccio/snekmate/pull/219))
- **Governance**
- [`TimelockController`](https://github.com/pcaversaccio/snekmate/blob/v0.1.0/src/snekmate/governance/TimelockController.vy): Make `TimelockController` module-friendly. ([#220](https://github.com/pcaversaccio/snekmate/pull/220))
- **Utility Functions**
- [`Base64`](https://github.com/pcaversaccio/snekmate/blob/v0.1.0/src/snekmate/utils/Base64.vy): Make `Base64` module-friendly. ([#222](https://github.com/pcaversaccio/snekmate/pull/222))
- **Vyper Contract Deployer**
- [`VyperDeployer`](https://github.com/pcaversaccio/snekmate/blob/v0.1.0/lib/utils/VyperDeployer.sol): Improve error message in the event of a Vyper compilation error. ([#219](https://github.com/pcaversaccio/snekmate/pull/219))

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ src
├── Math — "Standard Mathematical Utility Functions"
├── MerkleProofVerification — "Merkle Tree Proof Verification Functions"
├── Multicall — "Multicall Functions"
└── interfaces
└── IERC5267 — "EIP-5267 Interface Definition"
├── interfaces
│ └── IERC5267 — "EIP-5267 Interface Definition"
└── mocks
└── Base64Mock — "Base64 Module Reference Implementation"
```

## 🎛 Installation
Expand Down
8 changes: 4 additions & 4 deletions src/snekmate/utils/Base64.vy
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ def __init__():
pass


@external
@internal
@pure
def encode(data: Bytes[_DATA_INPUT_BOUND], base64_url: bool) -> DynArray[String[4], _DATA_OUTPUT_BOUND]:
def _encode(data: Bytes[_DATA_INPUT_BOUND], base64_url: bool) -> DynArray[String[4], _DATA_OUTPUT_BOUND]:
"""
@dev Encodes a `Bytes` array using the Base64
binary-to-text encoding scheme.
Expand Down Expand Up @@ -144,9 +144,9 @@ def encode(data: Bytes[_DATA_INPUT_BOUND], base64_url: bool) -> DynArray[String[
return char_chunks


@external
@internal
@pure
def decode(data: String[_DATA_OUTPUT_BOUND], base64_url: bool) -> DynArray[Bytes[3], _DATA_INPUT_BOUND]:
def _decode(data: String[_DATA_OUTPUT_BOUND], base64_url: bool) -> DynArray[Bytes[3], _DATA_INPUT_BOUND]:
"""
@dev Decodes a `String` input using the Base64
binary-to-text encoding scheme.
Expand Down
73 changes: 73 additions & 0 deletions src/snekmate/utils/mocks/Base64Mock.vy
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# pragma version ~=0.4.0b5
"""
@title Base64 Module Reference Implementation
@custom:contract-name Base64Mock
@license GNU Affero General Public License v3.0 only
@author pcaversaccio
"""


# @dev We import and initialise the `Base64` module.
from .. import Base64 as b64
initializes: b64


@deploy
@payable
def __init__():
"""
@dev To omit the opcodes for checking the `msg.value`
in the creation-time EVM bytecode, the constructor
is declared as `payable`.
"""
b64.__init__()


@external
@pure
def encode(data: Bytes[b64._DATA_INPUT_BOUND], base64_url: bool) -> DynArray[String[4], b64._DATA_OUTPUT_BOUND]:
"""
@dev Encodes a `Bytes` array using the Base64
binary-to-text encoding scheme.
@notice Due to the Vyper design with fixed-size
string parameters, string concatenations
with itself in a loop can lead to length
mismatches (the underlying issue is that
Vyper does not support a mutable `Bytes`
type). To circumvent this issue, we choose
a dynamic array as the return type.
@param data The maximum 1,024-byte data to be
Base64-encoded.
@param base64_url The Boolean variable that specifies
whether to use a URL and filename-safe alphabet
or not.
@return DynArray The maximum 4-character user-readable
string array that combined results in the Base64
encoding of `data`.
"""
return b64._encode(data, base64_url)


@external
@pure
def decode(data: String[b64._DATA_OUTPUT_BOUND], base64_url: bool) -> DynArray[Bytes[3], b64._DATA_INPUT_BOUND]:
"""
@dev Decodes a `String` input using the Base64
binary-to-text encoding scheme.
@notice Due to the Vyper design with fixed-size
byte parameters, byte concatenations
with itself in a loop can lead to length
mismatches (the underlying issue is that
Vyper does not support a mutable `Bytes`
type). To circumvent this issue, we choose
a dynamic array as the return type. Note
that line breaks are not supported.
@param data The maximum 1,368-byte data to be
Base64-decoded.
@param base64_url The Boolean variable that specifies
whether to use a URL and filename-safe alphabet
or not.
@return DynArray The maximum 3-byte array that combined
results in the Base64 decoding of `data`.
"""
return b64._decode(data, base64_url)
5 changes: 4 additions & 1 deletion test/utils/Base64.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ contract Base64Test is PRBTest {

function setUp() public {
base64 = IBase64(
vyperDeployer.deployContract("src/snekmate/utils/", "Base64")
vyperDeployer.deployContract(
"src/snekmate/utils/mocks/",
"Base64Mock"
)
);
}

Expand Down