Skip to content

Instantly share code, notes, and snippets.

@rfikki
Created May 15, 2026 17:30
Show Gist options
  • Select an option

  • Save rfikki/d7ca14d522f9d88c63137e78610c0c86 to your computer and use it in GitHub Desktop.

Select an option

Save rfikki/d7ca14d522f9d88c63137e78610c0c86 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
interface LegacyDinero {
function balanceOf(address owner) external view returns (uint256);
function transfer(address to, uint256 value) external;
}
contract DropBox {
address public immutable wrapper;
constructor(address _wrapper) {
wrapper = _wrapper;
}
function collect(LegacyDinero token, uint256 value) external {
require(msg.sender == wrapper, "Only wrapper can collect");
token.transfer(wrapper, value);
}
}
contract WrappedDinero is
ERC20,
ERC20Permit,
ERC20Burnable,
Ownable,
ReentrancyGuard,
Pausable
{
event DropBoxCreated(address indexed user, address dropBox);
event Wrapped(address indexed user, uint256 amount);
event Unwrapped(address indexed user, uint256 amount);
LegacyDinero public immutable legacyToken = LegacyDinero(0x374642afe485d1a181b01f5b028d169be58f3106);
mapping(address => address) public dropBoxes;
constructor()
ERC20("WrappedDinero", "DINO")
ERC20Permit("WrappedDinero") // Same name for EIP-2612 domain
Ownable(msg.sender)
{}
function createDropBox() external {
require(dropBoxes[msg.sender] == address(0), "Drop box already exists");
address db = address(new DropBox(address(this)));
dropBoxes[msg.sender] = db;
emit DropBoxCreated(msg.sender, db);
}
function wrap(uint256 value) external nonReentrant whenNotPaused {
address db = dropBoxes[msg.sender];
require(db != address(0), "Create drop box first");
require(legacyToken.balanceOf(db) >= value, "Not enough Dinero in drop box");
DropBox(db).collect(legacyToken, value);
_mint(msg.sender, value);
emit Wrapped(msg.sender, value);
}
function unwrap(uint256 value) external nonReentrant whenNotPaused {
require(balanceOf(msg.sender) >= value, "Not enough wrapped Dinero");
_burn(msg.sender, value);
legacyToken.transfer(msg.sender, value);
emit Unwrapped(msg.sender, value);
}
function decimals() public pure override returns (uint8) {
return 2;
}
function maxSupply() external view returns (uint256) {
return legacyToken.balanceOf(address(this));
}
// === Admin Functions ===
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function recoverStuckToken(address token, uint256 amount) external onlyOwner {
require(token != address(legacyToken), "Use unwrap() for legacy Dinero");
ERC20(token).transfer(owner(), amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment