Skip to content
Open
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
40 changes: 40 additions & 0 deletions src/Token.sol
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,46 @@ contract Token is
_setMintAllowance(account, amount);
}

/**
* @notice Allows a system account to set the mint allowance for an admin account, using an admin's signature for authorization.
*
* The message expected to be signed by the admin is currently hardcoded with a static hash
* (`0xb77c35c892a1b24b10a2ce49b424e578472333ee8d2456234fff90626332c50f`). This choice could be updated in future
* implementations to allow for dynamic messages, depending on design requirements.
*
* Requirements:
* - `from` must provide a valid signature matching the hardcoded hash to confirm authorization.
* - `from` must be a recognized admin account.
* - The function can only be called by accounts designated as system accounts.
*
* @param from The address of the admin providing authorization for setting the mint allowance.
* @param account The address of the account for which the mint allowance is to be set.
* @param amount The new mint allowance to be assigned to the specified account.
* @param signature The signature of the admin (`from`), authorizing this allowance adjustment.
*/

function setMintAllowanceForAdmin(
address from,
address account,
uint256 amount,
bytes memory signature
) public onlySystemAccounts {
require(
from.isValidSignatureNow(
0xb77c35c892a1b24b10a2ce49b424e578472333ee8d2456234fff90626332c50f, //change this hash to chosen static message hash
signature
),
"signature/hash does not match"
);

require(
isAdminAccount(from),
"Token: from is not a admin account"
);

_setMintAllowance(account, amount);
}

// EIP-2612 helper
function getPermitDigest(
address owner,
Expand Down
83 changes: 83 additions & 0 deletions test/Mintable.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,89 @@ contract MintableTokenTest is Test {
assertEq(token.balanceOf(user), 100);
}


function test_system_account_can_set_mint_allowance_for_an_admin()
public
{
test_owner_can_set_max_mint_allowance();
address user = vm.addr(userPrivateKey);

token.addAdminAccount(user);
token.addSystemAccount(system);

bytes32 hash = 0xb77c35c892a1b24b10a2ce49b424e578472333ee8d2456234fff90626332c50f;
(uint8 v, bytes32 r, bytes32 s) = vm.sign(userPrivateKey, hash);
bytes memory signature = abi.encodePacked(r, s, v);

vm.startPrank(system);
token.setMintAllowanceForAdmin(user, system, 1000, signature);
vm.stopPrank();

assertEq(token.getMintAllowance(system), 1000);

}

function test_system_account_cannot_set_mint_allowance_for_an_admin_with_wrong_signature()
public
{
test_owner_can_set_max_mint_allowance();
address user = vm.addr(userPrivateKey);

token.addAdminAccount(user);
token.addSystemAccount(system);

bytes32 hash = 0xb77c35c892a1b24b10a2ce49b424e578472333ee8d2456234fff90626332c50f;
(uint8 v, bytes32 r, bytes32 s) = vm.sign(userPrivateKey, hash);
r = bytes32(uint256(r) ^ 1); // Flip one bit in `r` to invalidate the signature
bytes memory signature = abi.encodePacked(r, s, v);


vm.startPrank(system);
vm.expectRevert("signature/hash does not match");
token.setMintAllowanceForAdmin(user, system, 1000, signature);
vm.stopPrank();
}

function test_system_account_cannot_set_mint_allowance_for_an_admin_with_wrong_messae()
public
{
test_owner_can_set_max_mint_allowance();
address user = vm.addr(userPrivateKey);

token.addAdminAccount(user);
token.addSystemAccount(system);

bytes32 hash = 0x0000000000000000000000000000000000000000000000000000000000001234;
(uint8 v, bytes32 r, bytes32 s) = vm.sign(userPrivateKey, hash);
r = bytes32(uint256(r) ^ 1); // Flip one bit in `r` to invalidate the signature
bytes memory signature = abi.encodePacked(r, s, v);


vm.startPrank(system);
vm.expectRevert("signature/hash does not match");
token.setMintAllowanceForAdmin(user, system, 1000, signature);
vm.stopPrank();
}

function test_system_account_cannot_set_mint_allowance_for_a_non_admin()
public
{
test_owner_can_set_max_mint_allowance();
address user = vm.addr(userPrivateKey);

// Not adding the user as admin
token.addSystemAccount(system);

bytes32 hash = 0xb77c35c892a1b24b10a2ce49b424e578472333ee8d2456234fff90626332c50f;
(uint8 v, bytes32 r, bytes32 s) = vm.sign(userPrivateKey, hash);
bytes memory signature = abi.encodePacked(r, s, v);

vm.startPrank(system);
vm.expectRevert("Token: from is not a admin account");
token.setMintAllowanceForAdmin(user, system, 1000, signature);
vm.stopPrank();
}

function test_system_account_cannot_mint_tokens_above_mint_allowance()
public
{
Expand Down