Skip to content

Commit 6b738b0

Browse files
committed
Merge branch 'main' into mike/update_consts_manager
# Conflicts: # contracts/sfc/SFC.sol
2 parents 4d29843 + 05eba01 commit 6b738b0

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

contracts/sfc/SFC.sol

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version {
152152
// values
153153
error ZeroAmount();
154154
error ZeroRewards();
155+
error ValueTooLarge();
155156

156157
// pubkeys
157158
error PubkeyUsedByOtherValidator();
@@ -216,7 +217,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version {
216217
);
217218
event ClaimedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 rewards);
218219
event RestakedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 rewards);
219-
event BurntFTM(uint256 amount);
220+
event BurntNativeTokens(uint256 amount);
220221
event UpdatedSlashingRefundRatio(uint256 indexed validatorID, uint256 refundRatio);
221222
event RefundedSlashedLegacyDelegation(address indexed delegator, uint256 indexed validatorID, uint256 amount);
222223
event AnnouncedRedirection(address indexed from, address indexed to);
@@ -459,9 +460,12 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version {
459460
emit TreasuryFeesResolved(fees);
460461
}
461462

462-
/// burnFTM allows SFC to burn an arbitrary amount of FTM tokens.
463-
function burnFTM(uint256 amount) external onlyOwner {
464-
_burnFTM(amount);
463+
/// Burn native tokens by sending them to the SFC contract.
464+
function burnNativeTokens() external payable {
465+
if (msg.value == 0) {
466+
revert ZeroAmount();
467+
}
468+
_burnNativeTokens(msg.value);
465469
}
466470

467471
/// Issue tokens to the issued tokens recipient as a counterparty to the burnt FTM tokens.
@@ -753,7 +757,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version {
753757
if (!sent) {
754758
revert TransferFailed();
755759
}
756-
_burnFTM(penalty);
760+
_burnNativeTokens(penalty);
757761

758762
emit Withdrawn(delegator, toValidatorID, wrID, amount - penalty, penalty);
759763
}
@@ -817,12 +821,16 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version {
817821
return rewards;
818822
}
819823

820-
/// Burn FTM tokens.
824+
/// Burn native tokens.
821825
/// The tokens are sent to the zero address.
822-
function _burnFTM(uint256 amount) internal {
826+
function _burnNativeTokens(uint256 amount) internal {
823827
if (amount != 0) {
828+
if (amount > totalSupply) {
829+
revert ValueTooLarge();
830+
}
831+
totalSupply -= amount;
824832
payable(address(0)).transfer(amount);
825-
emit BurntFTM(amount);
833+
emit BurntNativeTokens(amount);
826834
}
827835
}
828836

test/SFC.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { BlockchainNode, ValidatorMetrics } from './helpers/BlockchainNode';
88
describe('SFC', () => {
99
const fixture = async () => {
1010
const [owner, user] = await ethers.getSigners();
11+
const totalSupply = ethers.parseEther('100');
1112
const sfc = await upgrades.deployProxy(await ethers.getContractFactory('UnitTestSFC'), {
1213
kind: 'uups',
1314
initializer: false,
@@ -24,7 +25,7 @@ describe('SFC', () => {
2425
const evmWriter: IEVMWriter = await ethers.deployContract('StubEvmWriter');
2526
const initializer: UnitTestNetworkInitializer = await ethers.deployContract('UnitTestNetworkInitializer');
2627

27-
await initializer.initializeAll(0, 0, sfc, nodeDriverAuth, nodeDriver, evmWriter, owner);
28+
await initializer.initializeAll(0, totalSupply, sfc, nodeDriverAuth, nodeDriver, evmWriter, owner);
2829
const constants: UnitTestConstantsManager = await ethers.getContractAt(
2930
'UnitTestConstantsManager',
3031
await sfc.constsAddress(),
@@ -39,6 +40,7 @@ describe('SFC', () => {
3940
nodeDriver,
4041
nodeDriverAuth,
4142
constants,
43+
totalSupply,
4244
};
4345
};
4446

@@ -55,6 +57,32 @@ describe('SFC', () => {
5557
).to.revertedWithCustomError(this.sfc, 'TransfersNotAllowed');
5658
});
5759

60+
describe('Burn native tokens', () => {
61+
it('Should revert when no amount sent', async function () {
62+
await expect(this.sfc.connect(this.user).burnNativeTokens()).to.be.revertedWithCustomError(
63+
this.sfc,
64+
'ZeroAmount',
65+
);
66+
});
67+
68+
it('Should revert when amount greater than total supply', async function () {
69+
await expect(
70+
this.sfc.connect(this.user).burnNativeTokens({ value: this.totalSupply + 1n }),
71+
).to.be.revertedWithCustomError(this.sfc, 'ValueTooLarge');
72+
});
73+
74+
it('Should succeed and burn native tokens', async function () {
75+
const amount = ethers.parseEther('1.5');
76+
const totalSupply = await this.sfc.totalSupply();
77+
const tx = await this.sfc.connect(this.user).burnNativeTokens({ value: amount });
78+
await expect(tx).to.emit(this.sfc, 'BurntNativeTokens').withArgs(amount);
79+
expect(await this.sfc.totalSupply()).to.equal(totalSupply - amount);
80+
await expect(tx).to.changeEtherBalance(this.sfc, 0);
81+
await expect(tx).to.changeEtherBalance(this.user, -amount);
82+
await expect(tx).to.changeEtherBalance(ethers.ZeroAddress, amount);
83+
});
84+
});
85+
5886
describe('Genesis validator', () => {
5987
beforeEach(async function () {
6088
const validator = ethers.Wallet.createRandom();

0 commit comments

Comments
 (0)