diff --git a/.forge-snapshots/SwiseToken_burn.snap b/.forge-snapshots/SwiseToken_burn.snap new file mode 100644 index 0000000..a50600e --- /dev/null +++ b/.forge-snapshots/SwiseToken_burn.snap @@ -0,0 +1 @@ +51418 \ No newline at end of file diff --git a/.forge-snapshots/SwiseToken_mint.snap b/.forge-snapshots/SwiseToken_mint.snap new file mode 100644 index 0000000..65c237f --- /dev/null +++ b/.forge-snapshots/SwiseToken_mint.snap @@ -0,0 +1 @@ +92566 \ No newline at end of file diff --git a/.forge-snapshots/SwiseToken_permit.snap b/.forge-snapshots/SwiseToken_permit.snap new file mode 100644 index 0000000..882e9ed --- /dev/null +++ b/.forge-snapshots/SwiseToken_permit.snap @@ -0,0 +1 @@ +96845 \ No newline at end of file diff --git a/.forge-snapshots/SwiseToken_setController.snap b/.forge-snapshots/SwiseToken_setController.snap new file mode 100644 index 0000000..66b2f7b --- /dev/null +++ b/.forge-snapshots/SwiseToken_setController.snap @@ -0,0 +1 @@ +69655 \ No newline at end of file diff --git a/broadcast/DeploySwiseToken.s.sol/42161/run-latest.json b/broadcast/DeploySwiseToken.s.sol/42161/run-latest.json new file mode 100644 index 0000000..05e2367 --- /dev/null +++ b/broadcast/DeploySwiseToken.s.sol/42161/run-latest.json @@ -0,0 +1,68 @@ +{ + "transactions": [ + { + "hash": "0x4a355d1e857b14c59ba049eb322ae9609f109d0e50ab49ab67ae0fdbdcdcf7e9", + "transactionType": "CREATE", + "contractName": "SwiseToken", + "contractAddress": "0x4026affabd9032bcc87fa05c02f088905f3dc09b", + "function": null, + "arguments": [ + "0x105A9F815D5A871997F1877f5eF77EEF1fA31Ab8", + "\"StakeWise\"", + "\"SWISE\"" + ], + "transaction": { + "from": "0x105a9f815d5a871997f1877f5ef77eef1fa31ab8", + "gas": "0x7b84a1", + "value": "0x0", + "input": "0x61016060409080825234620004b05762001af78038038091620000238285620004b5565b83398101606082820312620004b05781516001600160a01b039384821691829003620004b0576020848101516001600160401b039590868111620004b057856200006f918301620004fe565b9483820151878111620004b057620000889201620004fe565b91805192818401848110888211176200049a57825260019081855283850195603160f81b87528015620004825782546001600160a01b0319908116845560008054918216831781559a167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08b80a386518881116200046e576005918254918483811c9316801562000463575b878410146200044f57601f9283811162000407575b5080878d858311600114620003a1579162000395575b50600019600383901b1c191690851b1783555b8051928a84116200038157600654908582811c9216801562000376575b8883101462000362578382116200031b575b505085918311600114620002b5579282939183928c94620002a9575b50501b916000199060031b1c1916176006555b620001bb8562000559565b93610120948552620001cd8462000717565b95610140968752838151910120938460e05251902096610100978089524660a0528251938401947f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f86528385015260608401524660808401523060a084015260a0835260c0830196838810908811176200029557508590525190206080523060c05261128893846200086f853960805184610dc8015260a05184610e94015260c05184610d92015260e05184610e1701525183610e3d015251826106620152518161068c0152f35b634e487b7160e01b81526041600452602490fd5b0151925038806200019d565b60068b52858b20919083601f1981168d5b8988838310620003035750505010620002e9575b505050811b01600655620001b0565b015160001960f88460031b161c19169055388080620002da565b868601518855909601959485019487935001620002c6565b60068d52878d209084808701821c8301938a881062000358575b01901c019085905b8281106200034c575062000181565b8d81550185906200033d565b9350829362000335565b634e487b7160e01b8d52602260045260248dfd5b91607f16916200016f565b634e487b7160e01b8c52604160045260248cfd5b90508a0151386200013f565b8681528981208894509190601f198416908b8f5b838310620003ef575050508311620003d5575b5050811b01835562000152565b8c015160001960f88460031b161c191690553880620003c8565b84015185558a969094019392830192018b8f620003b5565b848d52878d2084808401871c8201928a851062000445575b01861c019086908e5b838210620004395750505062000129565b81550186908e62000428565b925081926200041f565b634e487b7160e01b8c52602260045260248cfd5b92607f169262000114565b634e487b7160e01b8a52604160045260248afd5b8351631e4fbdf760e01b815260006004820152602490fd5b634e487b7160e01b600052604160045260246000fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176200049a57604052565b60005b838110620004ed5750506000910152565b8181015183820152602001620004dc565b81601f82011215620004b05780516001600160401b0381116200049a576040519262000535601f8301601f191660200185620004b5565b81845260208284010111620004b057620005569160208085019101620004d9565b90565b805160209081811015620005d75750601f8251116200059557808251920151908083106200058657501790565b82600019910360031b1b161790565b604490620005c99260405193849263305a27a960e01b845280600485015282519283918260248701528686019101620004d9565b601f01601f19168101030190fd5b906001600160401b0382116200049a57600754926001938481811c911680156200070c575b83821014620006f657601f8111620006bc575b5081601f841160011462000650575092829391839260009462000644575b50501b916000199060031b1c19161760075560ff90565b0151925038806200062d565b919083601f198116600760005284600020946000905b88838310620006a1575050501062000687575b505050811b0160075560ff90565b015160001960f88460031b161c1916905538808062000679565b85870151885590960195948501948793509081019062000666565b600760005284601f84600020920160051c820191601f860160051c015b828110620006e95750506200060f565b60008155018590620006d9565b634e487b7160e01b600052602260045260246000fd5b90607f1690620005fc565b805160209081811015620007445750601f8251116200059557808251920151908083106200058657501790565b906001600160401b0382116200049a57600854926001938481811c9116801562000863575b83821014620006f657601f811162000829575b5081601f8411600114620007bd5750928293918392600094620007b1575b50501b916000199060031b1c19161760085560ff90565b0151925038806200079a565b919083601f198116600860005284600020946000905b888383106200080e5750505010620007f4575b505050811b0160085560ff90565b015160001960f88460031b161c19169055388080620007e6565b858701518855909601959485019487935090810190620007d3565b600860005284601f84600020920160051c820191601f860160051c015b828110620008565750506200077c565b6000815501859062000846565b90607f16906200076956fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306fdde0314610b0057508163095ea7b314610ad657816318160ddd14610ab857816323b872dd146109c4578163313ce567146109a85781633644e5151461098457816340c10f19146108c257816370a082311461088a578163715018a61461082557816379ba5097146107a25781637ecebe001461076a57816384b0196e1461064a5781638da5cb5b1461062257816392eefe9b1461059c57816395d89b41146104ae5781639dc29fac146103bb578163a9059cbb1461038a578163d505accf1461022257508063dd62ed3e146101da578063e30c3978146101b2578063f2fde38b146101425763f77c47911461011757600080fd5b3461013e578160031936011261013e57600a5490516001600160a01b039091168152602090f35b5080fd5b82346101af5760203660031901126101af5761015c610bf0565b610164610eba565b600180546001600160a01b0319166001600160a01b0392831690811790915582549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b80fd5b503461013e578160031936011261013e5760015490516001600160a01b039091168152602090f35b503461013e578060031936011261013e57806020926101f7610bf0565b6101ff610c0b565b6001600160a01b0391821683526003865283832091168252845220549051908152f35b8391503461013e5760e036600319011261013e5761023e610bf0565b610246610c0b565b906044359260643560843560ff811681036103865781421161036f5760018060a01b0390818516928389526009602052898920908154916001830190558a519060208201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98452868d840152858a1660608401528a608084015260a083015260c082015260c0815260e0810181811067ffffffffffffffff82111761035c578b5251902061032a91610321916102fb610d8f565b908c519161190160f01b83526002830152602282015260c43591604260a435922061113d565b909291926111cd565b16818103610341578661033e878787610ee6565b80f35b87516325c0072360e11b815292830152602482015260449150fd5b634e487b7160e01b8b526041875260248bfd5b875163313c898160e11b8152808401839052602490fd5b8680fd5b50503461013e578060031936011261013e576020906103b46103aa610bf0565b6024359033610caf565b5160018152f35b83833461013e578060031936011261013e576103d5610bf0565b600a549091602435916001600160a01b03908116330361049e57831692831561048757838552600260205281852054908382106104505750916020918596827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9587895260028652038288205582815403905551908152a380f35b915163391434e360e21b81526001600160a01b03909216828701908152602081019190915260408101929092529081906060010390fd5b8151634b637e8f60e11b8152808701869052602490fd5b8151634ca8886760e01b81528690fd5b8284346101af57806003193601126101af5781519182826006546104d181610c21565b9081845260209560019187600182169182600014610575575050600114610519575b5050506105159291610506910385610c8d565b51928284938452830190610bb0565b0390f35b9190869350600683527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b82841061055d57505050820101816105066105156104f3565b8054848a018601528895508794909301928101610544565b60ff19168782015293151560051b86019093019350849250610506915061051590506104f3565b9190503461061e57602036600319011261061e576105b8610bf0565b6105c0610eba565b6001600160a01b03169182156106105750600a80546001600160a01b03191683179055519081527f1304018cfe79741dcf02ba6b61d39cc4757d59395d03224d9925c7aa8300214690602090a180f35b905163d92e233d60e01b8152fd5b8280fd5b50503461013e578160031936011261013e57905490516001600160a01b039091168152602090f35b9190503461061e578260031936011261061e576106867f0000000000000000000000000000000000000000000000000000000000000000610f79565b926106b07f000000000000000000000000000000000000000000000000000000000000000061107d565b90825192602092602085019585871067ffffffffffffffff881117610757575092602061070d838896610700998b9996528686528151998a99600f60f81b8b5260e0868c015260e08b0190610bb0565b91898303908a0152610bb0565b924660608801523060808801528460a088015286840360c088015251928381520193925b82811061074057505050500390f35b835185528695509381019392810192600101610731565b634e487b7160e01b845260419052602483fd5b50503461013e57602036600319011261013e5760209181906001600160a01b03610792610bf0565b1681526009845220549051908152f35b9190503461061e578260031936011261061e57600154916001600160a01b0391338385160361080e5750506001600160a01b031991821660015582543392811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60249250519063118cdaa760e01b82523390820152fd5b83346101af57806003193601126101af5761083e610eba565b600180546001600160a01b03199081169091558154908116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50503461013e57602036600319011261013e5760209181906001600160a01b036108b2610bf0565b1681526002845220549051908152f35b9190503461061e578060031936011261061e576108dd610bf0565b600a5460243592916001600160a01b039182163303610974571692831561095f5780549083820180921161094c57927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928795558585526002835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b8251634ca8886760e01b81528590fd5b50503461013e578160031936011261013e576020906109a1610d8f565b9051908152f35b50503461013e578160031936011261013e576020905160128152f35b905082346101af5760603660031901126101af576109e0610bf0565b6109e8610c0b565b916044359360018060a01b038316808352600360205286832033845260205286832054916000198303610a24575b6020886103b4898989610caf565b868310610a8c578115610a75573315610a5e575082526003602090815286832033845281529186902090859003905582906103b487610a16565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b90503461061e578260031936011261061e5760209250549051908152f35b50503461013e578060031936011261013e576020906103b4610af6610bf0565b6024359033610ee6565b84843461013e578160031936011261013e578282600554610b2081610c21565b9081845260209560019187600182169182600014610575575050600114610b54575050506105159291610506910385610c8d565b9190869350600583527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b828410610b9857505050820101816105066105156104f3565b8054848a018601528895508794909301928101610b7f565b919082519283825260005b848110610bdc575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610bbb565b600435906001600160a01b0382168203610c0657565b600080fd5b602435906001600160a01b0382168203610c0657565b90600182811c92168015610c51575b6020831014610c3b57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610c30565b6040810190811067ffffffffffffffff821117610c7757604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610c7757604052565b916001600160a01b03808416928315610d765716928315610d5d576000908382526002602052604082205490838210610d2b575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef95876020965260028652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480610e91575b15610dea577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff821117610c775760405251902090565b507f00000000000000000000000000000000000000000000000000000000000000004614610dc1565b6000546001600160a01b03163303610ece57565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116918215610f605716918215610f475760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260038252604060002085600052825280604060002055604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b60ff8114610fb75760ff811690601f8211610fa55760405191610f9b83610c5b565b8252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600754816000610fca83610c21565b808352926020906001908181169081156110595750600114610ff8575b5050610ff592500382610c8d565b90565b91509260076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688936000925b8284106110415750610ff59450505081016020013880610fe7565b85548785018301529485019486945092810192611026565b91505060209250610ff594915060ff191682840152151560051b8201013880610fe7565b60ff811461109f5760ff811690601f8211610fa55760405191610f9b83610c5b565b506040516008548160006110b283610c21565b8083529260209060019081811690811561105957506001146110dc575050610ff592500382610c8d565b91509260086000527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3936000925b8284106111255750610ff59450505081016020013880610fe7565b8554878501830152948501948694509281019261110a565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116111c157926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156111b55780516001600160a01b038116156111ac57918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561123c57806111df575050565b600181036111f95760405163f645eedf60e01b8152600490fd5b6002810361121a5760405163fce698f760e01b815260048101839052602490fd5b6003146112245750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea26469706673582212203c8f881d048831e54a5fe9f722a7fb896512ce6ff6277a06455a68f2c97a2ecc64736f6c63430008160033000000000000000000000000105a9f815d5a871997f1877f5ef77eef1fa31ab8000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000095374616b6557697365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055357495345000000000000000000000000000000000000000000000000000000", + "nonce": "0x7", + "chainId": "0xa4b1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x5a2ada", + "logs": [ + { + "address": "0x4026affabd9032bcc87fa05c02f088905f3dc09b", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000105a9f815d5a871997f1877f5ef77eef1fa31ab8" + ], + "data": "0x", + "blockHash": "0x5abb706229bcb10628bda5ba084b86ca735001c42ed7342aba7380a76005cc4f", + "blockNumber": "0xd0ef9be", + "transactionHash": "0x4a355d1e857b14c59ba049eb322ae9609f109d0e50ab49ab67ae0fdbdcdcf7e9", + "transactionIndex": "0x2", + "logIndex": "0x1", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000400000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000010000400000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000200000", + "type": "0x2", + "transactionHash": "0x4a355d1e857b14c59ba049eb322ae9609f109d0e50ab49ab67ae0fdbdcdcf7e9", + "transactionIndex": "0x2", + "blockHash": "0x5abb706229bcb10628bda5ba084b86ca735001c42ed7342aba7380a76005cc4f", + "blockNumber": "0xd0ef9be", + "gasUsed": "0x56d376", + "effectiveGasPrice": "0x989680", + "from": "0x105a9f815d5a871997f1877f5ef77eef1fa31ab8", + "to": null, + "contractAddress": "0x4026affabd9032bcc87fa05c02f088905f3dc09b", + "gasUsedForL1": "0x44c5eb", + "l1BlockNumber": "0x131b393" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1717697139, + "chain": 42161, + "commit": "feadc98" +} \ No newline at end of file diff --git a/script/DeployOsToken.s.sol b/script/DeployOsToken.s.sol index 890f5fe..0ba642a 100644 --- a/script/DeployOsToken.s.sol +++ b/script/DeployOsToken.s.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.22; import {Script, console2} from "forge-std/Script.sol"; -import {OsToken} from "../src/OsToken.sol"; +import {OsToken} from "../src/tokens/OsToken.sol"; contract DeployOsToken is Script { function run() external { diff --git a/script/DeploySwiseToken.s.sol b/script/DeploySwiseToken.s.sol new file mode 100644 index 0000000..059c779 --- /dev/null +++ b/script/DeploySwiseToken.s.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity ^0.8.22; + +import {Script, console2} from "forge-std/Script.sol"; +import {SwiseToken} from "../src/tokens/SwiseToken.sol"; + +contract DeploySwiseToken is Script { + function run() external { + vm.startBroadcast(); + console2.log("Deploying from: ", msg.sender); + + // Deploy SwiseToken. + SwiseToken swiseToken = new SwiseToken(msg.sender, "StakeWise", "SWISE"); + console2.log("SwiseToken deployed at: ", address(swiseToken)); + + vm.stopBroadcast(); + } + + // excludes this contract from coverage report + function test() public {} +} diff --git a/src/OsToken.sol b/src/tokens/OsToken.sol similarity index 100% rename from src/OsToken.sol rename to src/tokens/OsToken.sol diff --git a/src/tokens/SwiseToken.sol b/src/tokens/SwiseToken.sol new file mode 100644 index 0000000..de56454 --- /dev/null +++ b/src/tokens/SwiseToken.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity ^0.8.22; + +import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol"; +import {ERC20Permit, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; +import {Errors} from "@stakewise-core/libraries/Errors.sol"; + +/** + * @title SwiseToken + * @author StakeWise + * @notice SwiseToken is an ERC20 token with permit and minting functionality + */ +contract SwiseToken is Ownable2Step, ERC20Permit { + /** + * @notice Emitted when the controller is updated + * @param newController The address of the new controller + */ + event ControllerUpdated(address newController); + + address public controller; + + /** + * @dev Constructor + * @param _owner The address of the contract owner + * @param _name The name of the ERC20 token + * @param _symbol The symbol of the ERC20 token + */ + constructor(address _owner, string memory _name, string memory _symbol) + ERC20(_name, _symbol) + ERC20Permit(_name) + Ownable(_owner) + {} + + /** + * @dev Throws if called by any account other than the controller. + */ + modifier onlyController() { + if (msg.sender != controller) revert Errors.AccessDenied(); + _; + } + + /** + * @notice Mint SwiseToken. Can only be called by the controller. + * @param account The address of the account to mint SwiseToken for + * @param value The amount of SwiseToken to mint + */ + function mint(address account, uint256 value) external onlyController { + _mint(account, value); + } + + /** + * @notice Burn SwiseToken. Can only be called by the controller. + * @param account The address of the account to burn SwiseToken for + * @param value The amount of SwiseToken to burn + */ + function burn(address account, uint256 value) external onlyController { + _burn(account, value); + } + + /** + * @notice Set the controller address. Can only be called by the owner. + * @param newController The address of the new controller + */ + function setController(address newController) external onlyOwner { + if (newController == address(0)) revert Errors.ZeroAddress(); + controller = newController; + emit ControllerUpdated(newController); + } +} diff --git a/test/OsToken.t.sol b/test/tokens/OsToken.t.sol similarity index 95% rename from test/OsToken.t.sol rename to test/tokens/OsToken.t.sol index a9d1343..008a892 100644 --- a/test/OsToken.t.sol +++ b/test/tokens/OsToken.t.sol @@ -7,8 +7,8 @@ import {Errors} from "@stakewise-core/libraries/Errors.sol"; import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; -import {OsToken, IOsToken} from "../src/OsToken.sol"; -import {SigUtils} from "./helpers/SigUtils.sol"; +import {OsToken, IOsToken} from "../../src/tokens/OsToken.sol"; +import {SigUtils} from "../helpers/SigUtils.sol"; contract OsTokenTest is Test, GasSnapshot { OsToken osToken; diff --git a/test/tokens/SwiseToken.t.sol b/test/tokens/SwiseToken.t.sol new file mode 100644 index 0000000..180b523 --- /dev/null +++ b/test/tokens/SwiseToken.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity ^0.8.22; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol"; +import {Errors} from "@stakewise-core/libraries/Errors.sol"; +import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; +import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {SwiseToken} from "../../src/tokens/SwiseToken.sol"; +import {SigUtils} from "../helpers/SigUtils.sol"; + +contract SwiseTokenTest is Test, GasSnapshot { + SwiseToken swiseToken; + + function setUp() public { + swiseToken = new SwiseToken(address(this), "test", "test"); + } + + function test_setController() public { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, address(1))); + vm.prank(address(1)); + swiseToken.setController(address(1)); + + vm.expectRevert(abi.encodeWithSelector(Errors.ZeroAddress.selector)); + swiseToken.setController(address(0)); + + vm.expectEmit(false, false, false, true); + emit SwiseToken.ControllerUpdated(address(1)); + + snapStart("SwiseToken_setController"); + swiseToken.setController(address(1)); + snapEnd(); + + assertEq(swiseToken.controller(), address(1)); + } + + function test_mint() public { + vm.expectRevert(Errors.AccessDenied.selector); + vm.prank(address(1)); + swiseToken.mint(address(1), 1); + + swiseToken.setController(address(this)); + + snapStart("SwiseToken_mint"); + swiseToken.mint(address(1), 1); + snapEnd(); + + assertEq(swiseToken.balanceOf(address(1)), 1); + } + + function test_burn() public { + vm.expectRevert(Errors.AccessDenied.selector); + vm.prank(address(1)); + swiseToken.burn(address(1), 1); + + swiseToken.setController(address(this)); + swiseToken.mint(address(1), 1); + + snapStart("SwiseToken_burn"); + swiseToken.burn(address(1), 1); + snapEnd(); + + assertEq(swiseToken.balanceOf(address(1)), 0); + } + + function test_Permit() public { + uint256 ownerPrivateKey = 0xA11CE; + address owner = vm.addr(ownerPrivateKey); + address spender = address(1); + + SigUtils sigUtils = new SigUtils(swiseToken.DOMAIN_SEPARATOR()); + SigUtils.Permit memory permit = + SigUtils.Permit({owner: owner, spender: spender, value: 1e18, nonce: 0, deadline: 1 days}); + + bytes32 digest = sigUtils.getTypedDataHash(permit); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest); + + snapStart("SwiseToken_permit"); + swiseToken.permit(permit.owner, permit.spender, permit.value, permit.deadline, v, r, s); + snapEnd(); + + assertEq(swiseToken.allowance(owner, spender), 1e18); + assertEq(swiseToken.nonces(owner), 1); + } +}