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
46 changes: 31 additions & 15 deletions contracts/governance/locker/staking/OmnichainStakingBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -156,25 +156,23 @@ abstract contract OmnichainStakingBase is

/// @inheritdoc IOmnichainStaking
function unstakeToken(uint256 tokenId) external {
_updateRewardsAll(msg.sender);
require(lockedByToken[tokenId] != address(0), "!tokenId");
address lockedBy_ = lockedByToken[tokenId];
if (_msgSender() != lockedBy_) {
revert InvalidUnstaker(_msgSender(), lockedBy_);
}

delete lockedByToken[tokenId];
lockedTokenIdNfts[_msgSender()] = _deleteAnElement(lockedTokenIdNfts[_msgSender()], tokenId);

// reset and burn voting power
_burn(msg.sender, power[tokenId]);
power[tokenId] = 0;

_unstakeToken(tokenId);
locker.safeTransferFrom(address(this), msg.sender, tokenId);
}

/// @inheritdoc IOmnichainStaking
function increaseLockDuration(uint256 tokenId, uint256 newLockDuration) external {
function unstakeAndWithdraw(uint256 tokenId) external nonReentrant {
_unstakeToken(tokenId);
uint256 lockedAmount = locker.locked(tokenId).amount;
locker.withdraw(tokenId);
assert(locker.underlying().transfer(msg.sender, lockedAmount));
}

/// @inheritdoc IOmnichainStaking
function increaseLockDuration(
uint256 tokenId,
uint256 newLockDuration
) external {
require(newLockDuration > 0, "!newLockAmount");

require(msg.sender == lockedByToken[tokenId], "!tokenId");
Expand Down Expand Up @@ -379,6 +377,24 @@ abstract contract OmnichainStakingBase is
return updatedArray;
}

function _unstakeToken(uint256 tokenId) internal {
_updateRewardsAll(msg.sender);
require(lockedByToken[tokenId] != address(0), "!tokenId");
address lockedBy_ = lockedByToken[tokenId];
if (_msgSender() != lockedBy_) {
revert InvalidUnstaker(_msgSender(), lockedBy_);
}

delete lockedByToken[tokenId];
lockedTokenIdNfts[_msgSender()] = _deleteAnElement(
lockedTokenIdNfts[_msgSender()],
tokenId
);
// reset and burn voting power
_burn(msg.sender, power[tokenId]);
power[tokenId] = 0;
}

/**
* @notice Called frequently to update the staking parameters associated to an address
* @param token The token for which the rewards are updated
Expand Down
7 changes: 7 additions & 0 deletions contracts/interfaces/governance/IOmnichainStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ interface IOmnichainStaking is IMultiTokenRewards, IVotes {
*/
function unstakeToken(uint256 tokenId) external;

/**
* @notice A single withdraw function to unstake NFT, transfer it back to
* the user, and also withdraw all tokens for `tokenId` from the locker.
* @param tokenId The ID of the regular token NFT to unstake and withdraw.
*/
function unstakeAndWithdraw(uint256 tokenId) external;

/**
* @notice Updates the lock duration for a specific NFT.
* @param tokenId The ID of the NFT for which to update the lock duration.
Expand Down
26 changes: 26 additions & 0 deletions deploy/imp-omnichain-staking-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { network } from "hardhat";
async function main(hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts } = hre;
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();

const contract = await deploy("OmnichainStakingTokenImpl", {
from: deployer,
contract: "OmnichainStakingToken",
autoMine: true,
skipIfAlreadyDeployed: true,
log: true,
});

console.log("OmnichainStakingTokenImpl deployed to:", contract.address);

if (network.name !== "hardhat") {
await hre.run("verify:verify", {
address: contract.address,
});
}
}

main.tags = ["OmnichainStakingTokenImpl"];
export default main;
57 changes: 39 additions & 18 deletions deployments/base/OmnichainStakingTokenImpl.json

Large diffs are not rendered by default.