Address
0x4e793cc5dedf6eae1bdd3240d6811a80aff358f3Current Holdings
$0.00
TXs sent
not counted
First Active
2026-01-15
block 25,538,304
Last Active
243 days ago
block 25,538,639
Funded By
not identified
Net worth historyi
No net-worth snapshots recorded yet
exact matchSentinelMinterV4solc 0.8.20+commit.a1b79de6runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts@4.9.3/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts@4.9.3/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts@4.9.3/access/Ownable.sol";
/// @title Sentinel Minter V4 - SALV Burn → SEN Mint Bridge (Fresh Deploy)
/// @notice Direct burn to burn address. Deploy new to point to SentinelV2.
/// @dev Identical logic to V3 but fresh instance so sentinel can be set.
contract SentinelMinterV4 is ReentrancyGuard, Ownable {
IERC20 public immutable salvToken = IERC20(0x7fBc0BDf643341b42cf691f3Dbbb193e41c3Cf9d);
address public immutable burnAddress = 0x0000000000000000000000000000000000000369;
uint256 public immutable genesisTimestamp;
uint256 public constant HALVING_INTERVAL = 365 days;
uint256 public constant MAX_HALVINGS = 4;
uint256 public constant INITIAL_MINT_NUMERATOR = 105;
uint256 public constant MINT_DENOMINATOR = 100;
uint256 public constant MIN_BURN_AMOUNT = 100 * 10**18;
address public sentinel;
event Minted(address indexed user, uint256 salvBurned, uint256 senMinted, uint256 currentPhase);
modifier whenSentinelSet() {
require(sentinel != address(0), "Sentinel address not set yet");
_;
}
constructor() {
genesisTimestamp = block.timestamp;
}
function mintFromSalv(uint256 salvAmount) external nonReentrant whenSentinelSet {
require(salvAmount >= MIN_BURN_AMOUNT, "Burn amount below minimum (100 SALV)");
require(salvToken.balanceOf(msg.sender) >= salvAmount, "Insufficient SALV balance");
require(salvToken.allowance(msg.sender, address(this)) >= salvAmount, "Approve SALV first");
salvToken.transferFrom(msg.sender, burnAddress, salvAmount);
uint256 phase = getCurrentHalvingPhase();
uint256 mintDivisor = (1 << phase);
if (phase >= MAX_HALVINGS) mintDivisor = 1 << MAX_HALVINGS;
uint256 senAmount = (salvAmount * INITIAL_MINT_NUMERATOR) / MINT_DENOMINATOR / mintDivisor;
require(senAmount > 0, "Resulting SEN amount too small");
(bool success, ) = sentinel.call(
abi.encodeWithSignature("mint(address,uint256)", msg.sender, senAmount)
);
require(success, "Failed to mint SEN");
emit Minted(msg.sender, salvAmount, senAmount, phase);
}
function getCurrentHalvingPhase() public view returns (uint256) {
uint256 timeElapsed = block.timestamp - genesisTimestamp;
uint256 phase = timeElapsed / HALVING_INTERVAL;
return phase > MAX_HALVINGS ? MAX_HALVINGS : phase;
}
function setSentinel(address _sentinel) external onlyOwner {
require(_sentinel != address(0), "Invalid Sentinel address");
require(sentinel == address(0), "Sentinel already set");
sentinel = _sentinel;
}
function rescueERC20(IERC20 token, address to, uint256 amount) external onlyOwner {
require(address(token) != address(salvToken), "Cannot rescue SALV");
token.transfer(to, amount);
}
}