Skip to content
Merged
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
8 changes: 8 additions & 0 deletions deploy-config/91342.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"AddressDojangResolver": "0x692009FE206C3F897867F6BF7B5B45506B747F9e",
"AttestationIndexer": "0x9C9Bf29880448aB39795a11b669e22A0f1d790ec",
"BalanceDojangResolver": "0x6FFa7ABc1E380Bb967C78D5E648EF804e1fE6dAd",
"DojangAttesterBook": "0xDA282E89244424E297Ce8e78089B54D043FB28B6",
"DojangScroll": "0xd5077b67dcb56caC8b270C7788FC3E6ee03F17B9",
"SchemaBook": "0x78cBb3413FBb6aF05EF1D21e646440e56baE3AD6"
}
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extra_output = ["storageLayout", "metadata"]
ffi = true
fs_permissions = [
{ access='read-write', path='./deployments/' },
{ access='read', path='./deploy-config/' },
{ access='read', path = './out/' }
]

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dojang",
"version": "0.1.0",
"version": "0.2.0",
"description": "Contracts for Dojang Service",
"engines": {
"node": ">=22.0.0"
Expand Down
80 changes: 80 additions & 0 deletions script/upgrade/Upgrade.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {console2 as console} from "forge-std/console2.sol";
import {Script} from "forge-std/Script.sol";
import {VmSafe} from "forge-std/Vm.sol";
import {ISemver} from "../../src/interfaces/ISemver.sol";
import {Strings} from "@openzeppelin-contracts/utils/Strings.sol";
import {DeployConfig} from "../utils/DeployConfig.s.sol";
import {UUPSUpgradeable} from "@openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

contract Upgrade is Script, DeployConfig {
uint256 internal deployerKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
address internal deployer = vm.addr(deployerKey);

uint256 internal upgraderKey = vm.envUint("UPGRADER_PRIVATE_KEY");
address internal upgrader = vm.addr(upgraderKey);

function run() public {
upgradeUUPSContract(getAddress(".SchemaBook"), "SchemaBook.sol", new bytes(0), new bytes(0));
upgradeUUPSContract(getAddress(".DojangAttesterBook"), "DojangAttesterBook.sol", new bytes(0), new bytes(0));
upgradeUUPSContract(getAddress(".AttestationIndexer"), "AttestationIndexer.sol", new bytes(0), new bytes(0));
upgradeUUPSContract(
getAddress(".AddressDojangResolver"), "AddressDojangResolver.sol", new bytes(0), new bytes(0)
);
upgradeUUPSContract(
getAddress(".BalanceDojangResolver"), "BalanceDojangResolver.sol", new bytes(0), new bytes(0)
);
upgradeUUPSContract(getAddress(".DojangScroll"), "DojangScroll.sol", new bytes(0), new bytes(0));
}

function upgradeUUPSContract(
address proxy,
string memory contractName,
bytes memory constructorData,
bytes memory initData
)
public
{
if (!_needsUpgrade(proxy, contractName, constructorData)) {
return;
}

console.log("\nStarting upgrade for %s", contractName);

vm.startBroadcast(deployerKey);
address newImpl = vm.deployCode(contractName, constructorData);
vm.stopBroadcast();

console.log("New Implementation contract at %s", newImpl);

vm.startBroadcast(upgraderKey);
UUPSUpgradeable(proxy).upgradeToAndCall(newImpl, initData);
vm.stopBroadcast();

console.log("Upgrade complete \n");
}

function _needsUpgrade(
address proxy,
string memory contractName,
bytes memory constructorData
)
internal
returns (bool)
{
(VmSafe.CallerMode m,,) = vm.readCallers();
require(m == VmSafe.CallerMode.None, "Only offchain");
Comment on lines +67 to +68
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure that this function should be simulated, not broadcast.


(bool success,) = proxy.staticcall(abi.encodeWithSelector(ISemver.version.selector));
if (!success) {
return true;
}
Comment on lines +70 to +73
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if version() interface is not implemented, needs to upgrade.


ISemver proxyContract = ISemver(proxy);
ISemver newImplContract = ISemver(vm.deployCode(contractName, constructorData));

return !Strings.equal(proxyContract.version(), newImplContract.version());
}
}
42 changes: 42 additions & 0 deletions script/utils/DeployConfig.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {console2 as console} from "forge-std/console2.sol";
import {stdJson} from "forge-std/StdJson.sol";
import {Vm} from "forge-std/Vm.sol";

abstract contract DeployConfig {
/// @notice Foundry cheatcode VM.
Vm private constant _vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));

string private _deployConfigJson;

function setUp() public virtual {
string memory deployConfigFilePath =
string.concat(_vm.projectRoot(), "/deploy-config/", _vm.toString(block.chainid), ".json");
_deployConfigJson = _vm.readFile(deployConfigFilePath);

console.log("Fetching deploy config from %s", deployConfigFilePath);
console.log("Connected to network with chainid %s", block.chainid);
}

function keyExists(string memory key) internal view returns (bool) {
return stdJson.keyExists(_deployConfigJson, key);
}

function getAddress(string memory key) internal view returns (address) {
return stdJson.readAddress(_deployConfigJson, key);
}

function getAddresses(string memory key) internal view returns (address[] memory) {
return stdJson.readAddressArray(_deployConfigJson, key);
}

function getBytes32(string memory key) internal view returns (bytes32) {
return stdJson.readBytes32(_deployConfigJson, key);
}

function getBytes(string memory key) internal view returns (bytes memory) {
return stdJson.readBytes(_deployConfigJson, key);
}
}
13 changes: 6 additions & 7 deletions src/AddressDojangResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,6 @@ contract AddressDojangResolver is
_setIndexer(indexer);
}

/**
* @dev See {ISemver-version}.
*/
function version() external pure returns (string memory) {
return "0.1.0";
}

/**
* @dev Initializes the contract
* @param admin The address to be granted with the default admin Role
Expand All @@ -78,6 +71,12 @@ contract AddressDojangResolver is
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
}

/// @notice Semantic version.
/// @custom:semver 0.2.0
function version() public pure virtual returns (string memory) {
return "0.2.0";
}

/// @inheritdoc SchemaResolverUpgradeable
/// @dev See {AllowlistResolverUpgradeable-onAttest}, and
/// {AddressIndexingResolverUpgradeable-onAttest}.
Expand Down
15 changes: 14 additions & 1 deletion src/AttestationIndexer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@ import {IAttestationIndexer} from "./interfaces/IAttestationIndexer.sol";
import {Predeploys} from "./libraries/Types.sol";
import {ZeroAddress} from "./libraries/Common.sol";
import {AttestationVerifier} from "./libraries/AttestationVerifier.sol";
import {ISemver} from "./interfaces/ISemver.sol";

/**
* @title Attestation Indexer
* @notice An indexer for EAS attestation.
*/
contract AttestationIndexer is UUPSUpgradeable, AccessControlUpgradeable, PausableUpgradeable, IAttestationIndexer {
contract AttestationIndexer is
UUPSUpgradeable,
AccessControlUpgradeable,
PausableUpgradeable,
IAttestationIndexer,
ISemver
{
using AttestationVerifier for Attestation;

/// @dev Predeployed reference to the EAS contract
Expand Down Expand Up @@ -141,6 +148,12 @@ contract AttestationIndexer is UUPSUpgradeable, AccessControlUpgradeable, Pausab
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
}

/// @notice Semantic version.
/// @custom:semver 0.2.0
function version() public pure virtual returns (string memory) {
return "0.2.0";
}

/**
* @notice Authorizes the upgrade of the contract.
* @dev Only those with the UPGRADER_ROLE can call this.
Expand Down
13 changes: 6 additions & 7 deletions src/BalanceDojangResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ contract BalanceDojangResolver is
_setIndexer(indexer);
}

/**
* @dev See {ISemver-version}.
*/
function version() external pure returns (string memory) {
return "0.1.0";
}

/**
* @dev Initializes the contract
* @param admin The address to be granted with the default admin Role
Expand All @@ -81,6 +74,12 @@ contract BalanceDojangResolver is
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
}

/// @notice Semantic version.
/// @custom:semver 0.2.0
function version() public pure virtual returns (string memory) {
return "0.2.0";
}

/// @inheritdoc SchemaResolverUpgradeable
/// @dev See {BalanceValidationResolverUpgradeable-onAttest}, {AllowlistResolverUpgradeable-onAttest}, and
/// {BalanceIndexingResolverUpgradeable-onAttest}.
Expand Down
9 changes: 8 additions & 1 deletion src/DojangAttesterBook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import {UUPSUpgradeable} from "@openzeppelin-contracts-upgradeable/proxy/utils/U
import {AccessControlUpgradeable} from "@openzeppelin-contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {ZeroAddress} from "./libraries/Common.sol";
import {DojangAttesterId} from "./libraries/Types.sol";
import {ISemver} from "./interfaces/ISemver.sol";

contract DojangAttesterBook is UUPSUpgradeable, AccessControlUpgradeable {
contract DojangAttesterBook is UUPSUpgradeable, AccessControlUpgradeable, ISemver {
// 0x635a0c1689ad5a7df2dedc643572aeaf20ebc2ba3151b047c687dd08ef00e591
bytes32 public constant UPGRADER_ROLE = keccak256("dojang.dojangattesterbook.upgrader");

Expand Down Expand Up @@ -81,6 +82,12 @@ contract DojangAttesterBook is UUPSUpgradeable, AccessControlUpgradeable {
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
}

/// @notice Semantic version.
/// @custom:semver 0.2.0
function version() public pure virtual returns (string memory) {
return "0.2.0";
}

/**
* @notice Authorizes the upgrade of the contract.
* @dev Only those with the UPGRADER_ROLE can call this.
Expand Down
9 changes: 8 additions & 1 deletion src/DojangScroll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import {AttestationVerifier} from "./libraries/AttestationVerifier.sol";
import {Predeploys, DojangAttesterId, DojangSchemaIds} from "./libraries/Types.sol";
import {SchemaBook} from "./SchemaBook.sol";
import {DojangAttesterBook} from "./DojangAttesterBook.sol";
import {ISemver} from "./interfaces/ISemver.sol";

/**
* @title Dojang Scroll
* @notice Provides view access to issued "dojang" via EAS
* attestations
*/
contract DojangScroll is UUPSUpgradeable, AccessControlUpgradeable, IDojangScroll {
contract DojangScroll is UUPSUpgradeable, AccessControlUpgradeable, IDojangScroll, ISemver {
using AttestationVerifier for Attestation;

/// @dev Predeployed reference to the EAS contract
Expand Down Expand Up @@ -175,6 +176,12 @@ contract DojangScroll is UUPSUpgradeable, AccessControlUpgradeable, IDojangScrol
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
}

/// @notice Semantic version.
/// @custom:semver 0.2.0
function version() public pure virtual returns (string memory) {
return "0.2.0";
}

/**
* @notice Authorizes the upgrade of the contract.
* @dev Only those with the UPGRADER_ROLE can call this.
Expand Down
9 changes: 8 additions & 1 deletion src/SchemaBook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {AccessControlUpgradeable} from "@openzeppelin-contracts-upgradeable/acce
import {ZeroAddress} from "./libraries/Common.sol";
import {ISchemaRegistry} from "@eas-contracts/contracts/ISchemaRegistry.sol";
import {Predeploys} from "./libraries/Types.sol";
import {ISemver} from "./interfaces/ISemver.sol";

contract SchemaBook is UUPSUpgradeable, AccessControlUpgradeable {
contract SchemaBook is UUPSUpgradeable, AccessControlUpgradeable, ISemver {
/// @dev Predeployed reference to the SchemaRegistry contract
ISchemaRegistry private constant _SCHEMA_REGISTRY = ISchemaRegistry(Predeploys.SCHEMA_REGISTRY);

Expand Down Expand Up @@ -104,6 +105,12 @@ contract SchemaBook is UUPSUpgradeable, AccessControlUpgradeable {
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
}

/// @notice Semantic version.
/// @custom:semver 0.2.0
function version() public pure virtual returns (string memory) {
return "0.2.0";
}

/**
* @notice Authorizes the upgrade of the contract.
* @dev Only those with the UPGRADER_ROLE can call this.
Expand Down
8 changes: 8 additions & 0 deletions src/interfaces/ISemver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

interface ISemver {
/// @notice Returns the current semantic version of the contract
/// @return The semantic version string of the contract (e.g. `1.2.3`)
function version() external view returns (string memory);
}
2 changes: 1 addition & 1 deletion test/AddressDojangResolver.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ contract AddressDojangResolver_Configure is AddressDojangResolver_Base {
}

function test_version() public view {
assertEq(addressDojangResolver.version(), "0.1.0");
assertEq(addressDojangResolver.version(), "0.2.0");
}
}

Expand Down
8 changes: 5 additions & 3 deletions test/AttestationIndexer.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ contract AttestationIndexer_Pause is AttestationIndexer_Base {
}

contract AttestationIndexerV2 is AttestationIndexer {
function version() public pure returns (uint32) {
return 2;
function version() public pure override returns (string memory) {
return "99.0.0";
}
}

Expand All @@ -112,13 +112,15 @@ contract AttestationIndexer_Upgrade is AttestationIndexer_Base {
}

function test_upgrade_succeeds_by_upgrader() public {
assertEq(attestationIndexer.version(), "0.2.0");

address newImpl = address(new AttestationIndexerV2());

vm.prank(upgrader);
attestationIndexer.upgradeToAndCall(newImpl, bytes(""));
AttestationIndexerV2 newAttestationIndexer = AttestationIndexerV2(address(attestationIndexer));

assertEq(newAttestationIndexer.version(), 2);
assertEq(newAttestationIndexer.version(), "99.0.0");
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/BalanceDojangResolver.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ contract BalanceDojangResolver_Configure is BalanceDojangResolver_Base {
}

function test_version() public view {
assertEq(balanceDojangResolver.version(), "0.1.0");
assertEq(balanceDojangResolver.version(), "0.2.0");
}
}

Expand Down
8 changes: 5 additions & 3 deletions test/DojangAttesterBook.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ contract DojangAttesterBook_Init is DojangAttesterBook_Base {
}

contract DojangAttesterBookV2 is DojangAttesterBook {
function version() public pure returns (uint8) {
return 2;
function version() public pure override returns (string memory) {
return "99.0.0";
}
}

Expand All @@ -67,13 +67,15 @@ contract DojangAttesterBook_Upgrade is DojangAttesterBook_Base {
}

function test_upgrade_succeeds_by_upgrader() public {
assertEq(attesterBook.version(), "0.2.0");

address newImpl = address(new DojangAttesterBookV2());

vm.prank(upgrader);
attesterBook.upgradeToAndCall(newImpl, bytes(""));
DojangAttesterBookV2 newAttesterBook = DojangAttesterBookV2(address(attesterBook));

assertEq(newAttesterBook.version(), 2);
assertEq(newAttesterBook.version(), "99.0.0");
}
}

Expand Down
Loading