diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index f8c975b42..bda113f8c 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -591,16 +591,41 @@ contract Lido is Versioned, StETHPermit, AragonApp { stakingRouter.deposit.value(depositsValue)(depositsCount, _stakingModuleId, _depositCalldata); } + /// @notice Mint stETH shares + /// @param _recipient recipient of the shares + /// @param _sharesAmount amount of shares to mint + /// @dev can be called only by accounting + function mintShares(address _recipient, uint256 _sharesAmount) public { + _auth(getLidoLocator().accounting()); + + _mintShares(_recipient, _sharesAmount); + // emit event after minting shares because we are always having the net new ether under the hood + // for vaults we have new locked ether and for fees we have a part of rewards + _emitTransferAfterMintingShares(_recipient, _sharesAmount); + } + + /// @notice Burn stETH shares from the sender address + /// @param _sharesAmount amount of shares to burn + /// @dev can be called only by burner + function burnShares(uint256 _sharesAmount) public { + _auth(getLidoLocator().burner()); + + _burnShares(msg.sender, _sharesAmount); + + // historically there is no events for this kind of burning + // TODO: should burn events be emitted here? + // maybe TransferShare for cover burn and all events for withdrawal burn + } + /// @notice Mint shares backed by external vaults /// /// @param _receiver Address to receive the minted shares /// @param _amountOfShares Amount of shares to mint - /// - /// @dev authentication goes through isMinter in StETH + /// @return stethAmount The amount of stETH minted + /// @dev can be called only by accounting (authentication in mintShares method) function mintExternalShares(address _receiver, uint256 _amountOfShares) external { - if (_receiver == address(0)) revert("MINT_RECEIVER_ZERO_ADDRESS"); - if (_amountOfShares == 0) revert("MINT_ZERO_AMOUNT_OF_SHARES"); - + require(_receiver != address(0), "MINT_RECEIVER_ZERO_ADDRESS"); + require(_amountOfShares != 0, "MINT_ZERO_AMOUNT_OF_SHARES"); _whenNotStakingPaused(); uint256 stethAmount = super.getPooledEthByShares(_amountOfShares); @@ -620,11 +645,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { /// @notice Burns external shares from a specified account /// /// @param _amountOfShares Amount of shares to burn - /// - /// @dev authentication goes through _isBurner() method function burnExternalShares(uint256 _amountOfShares) external { - if (_amountOfShares == 0) revert("BURN_ZERO_AMOUNT_OF_SHARES"); - + require(_amountOfShares != 0, "BURN_ZERO_AMOUNT_OF_SHARES"); + _auth(getLidoLocator().accounting()); _whenNotStakingPaused(); uint256 stethAmount = super.getPooledEthByShares(_amountOfShares); @@ -634,7 +657,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { EXTERNAL_BALANCE_POSITION.setStorageUint256(extBalance - stethAmount); - burnShares(msg.sender, _amountOfShares); + _burnShares(msg.sender, _amountOfShares); + + _emitTransferEvents(msg.sender, address(0), stethAmount, _amountOfShares); emit ExternalSharesBurned(msg.sender, _amountOfShares, stethAmount); } @@ -916,16 +941,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { return _getPooledEther().add(EXTERNAL_BALANCE_POSITION.getStorageUint256()); } - /// @dev override isMinter from StETH to allow accounting to mint - function _isMinter(address _sender) internal view returns (bool) { - return _sender == getLidoLocator().accounting(); - } - - /// @dev override isBurner from StETH to allow accounting to burn - function _isBurner(address _sender) internal view returns (bool) { - return _sender == getLidoLocator().burner() || _sender == getLidoLocator().accounting(); - } - function _pauseStaking() internal { STAKING_STATE_POSITION.setStorageStakeLimitStruct( STAKING_STATE_POSITION.getStorageStakeLimitStruct().setStakeLimitPauseState(true) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index 791ded8ef..6276da667 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -360,29 +360,6 @@ contract StETH is IERC20, Pausable { return tokensAmount; } - function mintShares(address _recipient, uint256 _sharesAmount) public { - require(_isMinter(msg.sender), "AUTH_FAILED"); - - _mintShares(_recipient, _sharesAmount); - _emitTransferAfterMintingShares(_recipient, _sharesAmount); - } - - function burnShares(address _account, uint256 _sharesAmount) public { - require(_isBurner(msg.sender), "AUTH_FAILED"); - - _burnShares(_account, _sharesAmount); - - // TODO: do something with Transfer event - } - - function _isMinter(address) internal view returns (bool) { - return false; - } - - function _isBurner(address) internal view returns (bool) { - return false; - } - /** * @return the total amount (in wei) of Ether controlled by the protocol. * @dev This is used for calculating tokens from shares and vice versa. diff --git a/contracts/0.8.9/Burner.sol b/contracts/0.8.9/Burner.sol index 80108bb1c..67fde46a8 100644 --- a/contracts/0.8.9/Burner.sol +++ b/contracts/0.8.9/Burner.sol @@ -14,9 +14,9 @@ import {IBurner} from "../common/interfaces/IBurner.sol"; import {ILidoLocator} from "../common/interfaces/ILidoLocator.sol"; /** - * @title Interface defining ERC20-compatible StETH token + * @title Interface defining Lido contract */ -interface IStETH is IERC20 { +interface ILido is IERC20 { /** * @notice Get stETH amount by the provided shares amount * @param _sharesAmount shares amount @@ -44,7 +44,11 @@ interface IStETH is IERC20 { address _sender, address _recipient, uint256 _sharesAmount ) external returns (uint256); - function burnShares(address _account, uint256 _amount) external; + /** + * @notice Burn shares from the account + * @param _amount amount of shares to burn + */ + function burnShares(uint256 _amount) external; } /** @@ -73,7 +77,7 @@ contract Burner is IBurner, AccessControlEnumerable { uint256 private totalNonCoverSharesBurnt; ILidoLocator public immutable LOCATOR; - IStETH public immutable STETH; + ILido public immutable LIDO; /** * Emitted when a new stETH burning request is added by the `requestedBy` address. @@ -148,7 +152,7 @@ contract Burner is IBurner, AccessControlEnumerable { _setupRole(REQUEST_BURN_SHARES_ROLE, _stETH); LOCATOR = ILidoLocator(_locator); - STETH = IStETH(_stETH); + LIDO = ILido(_stETH); totalCoverSharesBurnt = _totalCoverSharesBurnt; totalNonCoverSharesBurnt = _totalNonCoverSharesBurnt; @@ -166,8 +170,8 @@ contract Burner is IBurner, AccessControlEnumerable { * */ function requestBurnMyStETHForCover(uint256 _stETHAmountToBurn) external onlyRole(REQUEST_BURN_MY_STETH_ROLE) { - STETH.transferFrom(msg.sender, address(this), _stETHAmountToBurn); - uint256 sharesAmount = STETH.getSharesByPooledEth(_stETHAmountToBurn); + LIDO.transferFrom(msg.sender, address(this), _stETHAmountToBurn); + uint256 sharesAmount = LIDO.getSharesByPooledEth(_stETHAmountToBurn); _requestBurn(sharesAmount, _stETHAmountToBurn, true /* _isCover */); } @@ -183,7 +187,7 @@ contract Burner is IBurner, AccessControlEnumerable { * */ function requestBurnSharesForCover(address _from, uint256 _sharesAmountToBurn) external onlyRole(REQUEST_BURN_SHARES_ROLE) { - uint256 stETHAmount = STETH.transferSharesFrom(_from, address(this), _sharesAmountToBurn); + uint256 stETHAmount = LIDO.transferSharesFrom(_from, address(this), _sharesAmountToBurn); _requestBurn(_sharesAmountToBurn, stETHAmount, true /* _isCover */); } @@ -199,8 +203,8 @@ contract Burner is IBurner, AccessControlEnumerable { * */ function requestBurnMyStETH(uint256 _stETHAmountToBurn) external onlyRole(REQUEST_BURN_MY_STETH_ROLE) { - STETH.transferFrom(msg.sender, address(this), _stETHAmountToBurn); - uint256 sharesAmount = STETH.getSharesByPooledEth(_stETHAmountToBurn); + LIDO.transferFrom(msg.sender, address(this), _stETHAmountToBurn); + uint256 sharesAmount = LIDO.getSharesByPooledEth(_stETHAmountToBurn); _requestBurn(sharesAmount, _stETHAmountToBurn, false /* _isCover */); } @@ -216,7 +220,7 @@ contract Burner is IBurner, AccessControlEnumerable { * */ function requestBurnShares(address _from, uint256 _sharesAmountToBurn) external onlyRole(REQUEST_BURN_SHARES_ROLE) { - uint256 stETHAmount = STETH.transferSharesFrom(_from, address(this), _sharesAmountToBurn); + uint256 stETHAmount = LIDO.transferSharesFrom(_from, address(this), _sharesAmountToBurn); _requestBurn(_sharesAmountToBurn, stETHAmount, false /* _isCover */); } @@ -229,11 +233,11 @@ contract Burner is IBurner, AccessControlEnumerable { uint256 excessStETH = getExcessStETH(); if (excessStETH > 0) { - uint256 excessSharesAmount = STETH.getSharesByPooledEth(excessStETH); + uint256 excessSharesAmount = LIDO.getSharesByPooledEth(excessStETH); emit ExcessStETHRecovered(msg.sender, excessStETH, excessSharesAmount); - STETH.transfer(LOCATOR.treasury(), excessStETH); + LIDO.transfer(LOCATOR.treasury(), excessStETH); } } @@ -253,7 +257,7 @@ contract Burner is IBurner, AccessControlEnumerable { */ function recoverERC20(address _token, uint256 _amount) external { if (_amount == 0) revert ZeroRecoveryAmount(); - if (_token == address(STETH)) revert StETHRecoveryWrongFunc(); + if (_token == address(LIDO)) revert StETHRecoveryWrongFunc(); emit ERC20Recovered(msg.sender, _token, _amount); @@ -268,7 +272,7 @@ contract Burner is IBurner, AccessControlEnumerable { * @param _tokenId minted token id */ function recoverERC721(address _token, uint256 _tokenId) external { - if (_token == address(STETH)) revert StETHRecoveryWrongFunc(); + if (_token == address(LIDO)) revert StETHRecoveryWrongFunc(); emit ERC721Recovered(msg.sender, _token, _tokenId); @@ -307,7 +311,7 @@ contract Burner is IBurner, AccessControlEnumerable { uint256 sharesToBurnNowForCover = Math.min(_sharesToBurn, memCoverSharesBurnRequested); totalCoverSharesBurnt += sharesToBurnNowForCover; - uint256 stETHToBurnNowForCover = STETH.getPooledEthByShares(sharesToBurnNowForCover); + uint256 stETHToBurnNowForCover = LIDO.getPooledEthByShares(sharesToBurnNowForCover); emit StETHBurnt(true /* isCover */, stETHToBurnNowForCover, sharesToBurnNowForCover); coverSharesBurnRequested -= sharesToBurnNowForCover; @@ -320,14 +324,15 @@ contract Burner is IBurner, AccessControlEnumerable { ); totalNonCoverSharesBurnt += sharesToBurnNowForNonCover; - uint256 stETHToBurnNowForNonCover = STETH.getPooledEthByShares(sharesToBurnNowForNonCover); + uint256 stETHToBurnNowForNonCover = LIDO.getPooledEthByShares(sharesToBurnNowForNonCover); emit StETHBurnt(false /* isCover */, stETHToBurnNowForNonCover, sharesToBurnNowForNonCover); nonCoverSharesBurnRequested -= sharesToBurnNowForNonCover; sharesToBurnNow += sharesToBurnNowForNonCover; } - STETH.burnShares(address(this), _sharesToBurn); + + LIDO.burnShares(_sharesToBurn); assert(sharesToBurnNow == _sharesToBurn); } @@ -359,12 +364,12 @@ contract Burner is IBurner, AccessControlEnumerable { * Returns the stETH amount belonging to the burner contract address but not marked for burning. */ function getExcessStETH() public view returns (uint256) { - return STETH.getPooledEthByShares(_getExcessStETHShares()); + return LIDO.getPooledEthByShares(_getExcessStETHShares()); } function _getExcessStETHShares() internal view returns (uint256) { uint256 sharesBurnRequested = (coverSharesBurnRequested + nonCoverSharesBurnRequested); - uint256 totalShares = STETH.sharesOf(address(this)); + uint256 totalShares = LIDO.sharesOf(address(this)); // sanity check, don't revert if (totalShares <= sharesBurnRequested) { diff --git a/test/0.4.24/contracts/StETH__Harness.sol b/test/0.4.24/contracts/StETH__Harness.sol index 02140fc49..df914901f 100644 --- a/test/0.4.24/contracts/StETH__Harness.sol +++ b/test/0.4.24/contracts/StETH__Harness.sol @@ -6,10 +6,6 @@ pragma solidity 0.4.24; import {StETH} from "contracts/0.4.24/StETH.sol"; contract StETH__Harness is StETH { - address private mock__minter; - address private mock__burner; - bool private mock__shouldUseSuperGuards; - uint256 private totalPooledEther; constructor(address _holder) public payable { @@ -29,35 +25,15 @@ contract StETH__Harness is StETH { totalPooledEther = _totalPooledEther; } - function mock__setMinter(address _minter) public { - mock__minter = _minter; - } - - function mock__setBurner(address _burner) public { - mock__burner = _burner; - } - - function mock__useSuperGuards(bool _shouldUseSuperGuards) public { - mock__shouldUseSuperGuards = _shouldUseSuperGuards; - } - - function _isMinter(address _address) internal view returns (bool) { - if (mock__shouldUseSuperGuards) { - return super._isMinter(_address); - } - - return _address == mock__minter; + function harness__mintInitialShares(uint256 _sharesAmount) public { + _mintInitialShares(_sharesAmount); } - function _isBurner(address _address) internal view returns (bool) { - if (mock__shouldUseSuperGuards) { - return super._isBurner(_address); - } - - return _address == mock__burner; + function harness__mintShares(address _recipient, uint256 _sharesAmount) public { + _mintShares(_recipient, _sharesAmount); } - function harness__mintInitialShares(uint256 _sharesAmount) public { - _mintInitialShares(_sharesAmount); + function burnShares(uint256 _amount) external { + _burnShares(msg.sender, _amount); } } diff --git a/test/0.4.24/lido/lido.mintburning.test.ts b/test/0.4.24/lido/lido.mintburning.test.ts new file mode 100644 index 000000000..93189ed81 --- /dev/null +++ b/test/0.4.24/lido/lido.mintburning.test.ts @@ -0,0 +1,95 @@ +import { expect } from "chai"; +import { ZeroAddress } from "ethers"; +import { ethers } from "hardhat"; + +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; + +import { Lido } from "typechain-types"; + +import { ether, impersonate } from "lib"; + +import { deployLidoDao } from "test/deploy"; +import { Snapshot } from "test/suite"; + +describe("Lido.sol:mintburning", () => { + let deployer: HardhatEthersSigner; + let user: HardhatEthersSigner; + let accounting: HardhatEthersSigner; + let burner: HardhatEthersSigner; + + let lido: Lido; + + let originalState: string; + + before(async () => { + [deployer, user] = await ethers.getSigners(); + + ({ lido } = await deployLidoDao({ rootAccount: deployer, initialized: true })); + + const locator = await ethers.getContractAt("LidoLocator", await lido.getLidoLocator(), user); + + accounting = await impersonate(await locator.accounting(), ether("100.0")); + burner = await impersonate(await locator.burner(), ether("100.0")); + + lido = lido.connect(user); + }); + + beforeEach(async () => (originalState = await Snapshot.take())); + + afterEach(async () => await Snapshot.restore(originalState)); + + context("mintShares", () => { + it("Reverts when minter is not accounting", async () => { + await expect(lido.mintShares(user, 1n)).to.be.revertedWith("APP_AUTH_FAILED"); + }); + + it("Reverts when minting to zero address", async () => { + await expect(lido.connect(accounting).mintShares(ZeroAddress, 1n)).to.be.revertedWith("MINT_TO_ZERO_ADDR"); + }); + + it("Mints shares to the recipient and fires the transfer events", async () => { + await expect(lido.connect(accounting).mintShares(user, 1000n)) + .to.emit(lido, "TransferShares") + .withArgs(ZeroAddress, user.address, 1000n) + .to.emit(lido, "Transfer") + .withArgs(ZeroAddress, user.address, 999n); + + expect(await lido.sharesOf(user)).to.equal(1000n); + expect(await lido.balanceOf(user)).to.equal(999n); + }); + }); + + context("burnShares", () => { + it("Reverts when burner is not authorized", async () => { + await expect(lido.burnShares(1n)).to.be.revertedWith("APP_AUTH_FAILED"); + }); + + it("Reverts when burning more than the owner owns", async () => { + const sharesOfHolder = await lido.sharesOf(burner); + + await expect(lido.connect(burner).burnShares(sharesOfHolder + 1n)).to.be.revertedWith("BALANCE_EXCEEDED"); + }); + + it("Zero burn", async () => { + const sharesOfHolder = await lido.sharesOf(burner); + + await expect(lido.connect(burner).burnShares(sharesOfHolder)) + .to.emit(lido, "SharesBurnt") + .withArgs(burner.address, 0n, 0n, 0n); + + expect(await lido.sharesOf(burner)).to.equal(0n); + }); + + it("Burn shares from burner and emit SharesBurnt event", async () => { + await lido.connect(accounting).mintShares(burner, 1000n); + + const sharesOfHolder = await lido.sharesOf(burner); + + await expect(lido.connect(burner).burnShares(sharesOfHolder)) + .to.emit(lido, "SharesBurnt") + .withArgs(burner.address, await lido.getPooledEthByShares(1000n), 1000n, 1000n); + + expect(await lido.sharesOf(burner)).to.equal(0n); + }); + }); +}); diff --git a/test/0.4.24/steth.test.ts b/test/0.4.24/steth.test.ts index d254cce84..6948a9bb3 100644 --- a/test/0.4.24/steth.test.ts +++ b/test/0.4.24/steth.test.ts @@ -21,8 +21,6 @@ describe("StETH.sol:non-ERC-20 behavior", () => { let holder: HardhatEthersSigner; let recipient: HardhatEthersSigner; let spender: HardhatEthersSigner; - let minter: HardhatEthersSigner; - let burner: HardhatEthersSigner; // required for some strictly theoretical branch checks let zeroAddressSigner: HardhatEthersSigner; @@ -36,7 +34,7 @@ describe("StETH.sol:non-ERC-20 behavior", () => { before(async () => { zeroAddressSigner = await impersonate(ZeroAddress, ONE_ETHER); - [deployer, holder, recipient, spender, minter, burner] = await ethers.getSigners(); + [deployer, holder, recipient, spender] = await ethers.getSigners(); steth = await ethers.deployContract("StETH__Harness", [holder], { value: holderBalance, from: deployer }); steth = steth.connect(holder); @@ -464,64 +462,6 @@ describe("StETH.sol:non-ERC-20 behavior", () => { } }); - context("mintShares", () => { - it("Reverts when minter is not authorized", async () => { - await steth.mock__useSuperGuards(true); - - await expect(steth.mintShares(holder, 1n)).to.be.revertedWith("AUTH_FAILED"); - }); - - it("Reverts when minting to zero address", async () => { - await steth.mock__setMinter(minter); - - await expect(steth.connect(minter).mintShares(ZeroAddress, 1n)).to.be.revertedWith("MINT_TO_ZERO_ADDR"); - }); - - it("Mints shares to the recipient and fires the transfer events", async () => { - const sharesBeforeMint = await steth.sharesOf(holder); - await steth.mock__setMinter(minter); - - await expect(steth.connect(minter).mintShares(holder, 1000n)) - .to.emit(steth, "TransferShares") - .withArgs(ZeroAddress, holder.address, 1000n); - - expect(await steth.sharesOf(holder)).to.equal(sharesBeforeMint + 1000n); - }); - }); - - context("burnShares", () => { - it("Reverts when burner is not authorized", async () => { - await steth.mock__useSuperGuards(true); - await expect(steth.burnShares(holder, 1n)).to.be.revertedWith("AUTH_FAILED"); - }); - - it("Reverts when burning on zero address", async () => { - await steth.mock__setBurner(burner); - - await expect(steth.connect(burner).burnShares(ZeroAddress, 1n)).to.be.revertedWith("BURN_FROM_ZERO_ADDR"); - }); - - it("Reverts when burning more than the owner owns", async () => { - const sharesOfHolder = await steth.sharesOf(holder); - await steth.mock__setBurner(burner); - - await expect(steth.connect(burner).burnShares(holder, sharesOfHolder + 1n)).to.be.revertedWith( - "BALANCE_EXCEEDED", - ); - }); - - it("Burns shares from the owner and fires the transfer events", async () => { - const sharesOfHolder = await steth.sharesOf(holder); - await steth.mock__setBurner(burner); - - await expect(steth.connect(burner).burnShares(holder, 1000n)) - .to.emit(steth, "SharesBurnt") - .withArgs(holder.address, 1000n, 1000n, 1000n); - - expect(await steth.sharesOf(holder)).to.equal(sharesOfHolder - 1000n); - }); - }); - context("_mintInitialShares", () => { it("Mints shares to the recipient and fires the transfer events", async () => { const balanceOfInitialSharesHolderBefore = await steth.balanceOf(INITIAL_SHARES_HOLDER); diff --git a/test/0.8.25/vaults/contracts/StETH__HarnessForVaultHub.sol b/test/0.8.25/vaults/contracts/StETH__HarnessForVaultHub.sol index 3111f4bc1..8f50502b4 100644 --- a/test/0.8.25/vaults/contracts/StETH__HarnessForVaultHub.sol +++ b/test/0.8.25/vaults/contracts/StETH__HarnessForVaultHub.sol @@ -8,10 +8,6 @@ import {StETH} from "contracts/0.4.24/StETH.sol"; contract StETH__HarnessForVaultHub is StETH { uint256 internal constant TOTAL_BASIS_POINTS = 10000; - address private mock__minter; - address private mock__burner; - bool private mock__shouldUseSuperGuards; - uint256 private totalPooledEther; uint256 private externalBalance; uint256 private maxExternalBalanceBp = 100; //bp @@ -41,34 +37,6 @@ contract StETH__HarnessForVaultHub is StETH { totalPooledEther = _totalPooledEther; } - function mock__setMinter(address _minter) public { - mock__minter = _minter; - } - - function mock__setBurner(address _burner) public { - mock__burner = _burner; - } - - function mock__useSuperGuards(bool _shouldUseSuperGuards) public { - mock__shouldUseSuperGuards = _shouldUseSuperGuards; - } - - function _isMinter(address _address) internal view returns (bool) { - if (mock__shouldUseSuperGuards) { - return super._isMinter(_address); - } - - return _address == mock__minter; - } - - function _isBurner(address _address) internal view returns (bool) { - if (mock__shouldUseSuperGuards) { - return super._isBurner(_address); - } - - return _address == mock__burner; - } - function harness__mintInitialShares(uint256 _sharesAmount) public { _mintInitialShares(_sharesAmount); } diff --git a/test/0.8.9/burner.test.ts b/test/0.8.9/burner.test.ts index 5d18753e9..f683a3122 100644 --- a/test/0.8.9/burner.test.ts +++ b/test/0.8.9/burner.test.ts @@ -49,9 +49,6 @@ describe("Burner.sol", () => { // Accounting is granted the permission to burn shares as a part of the protocol setup accountingSigner = await impersonate(accounting, ether("1.0")); await burner.connect(admin).grantRole(await burner.REQUEST_BURN_SHARES_ROLE(), accountingSigner); - - await steth.mock__setBurner(await burner.getAddress()); - await steth.mock__setMinter(accounting); }); beforeEach(async () => (originalState = await Snapshot.take())); @@ -107,7 +104,7 @@ describe("Burner.sol", () => { expect(await burner.hasRole(requestBurnSharesRole, steth)).to.equal(true); expect(await burner.hasRole(requestBurnSharesRole, accounting)).to.equal(true); - expect(await burner.STETH()).to.equal(steth); + expect(await burner.LIDO()).to.equal(steth); expect(await burner.LOCATOR()).to.equal(locator); expect(await burner.getCoverSharesBurnt()).to.equal(coverSharesBurnt); @@ -665,7 +662,7 @@ describe("Burner.sol", () => { expect(coverShares).to.equal(0n); expect(nonCoverShares).to.equal(0n); - await steth.connect(accountingSigner).mintShares(burner, 1n); + await steth.connect(accountingSigner).harness__mintShares(burner, 1n); expect(await burner.getExcessStETH()).to.equal(0n); });