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
15 changes: 5 additions & 10 deletions abi/VESTArElection.json
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,6 @@
"type": "tuple",
"internalType": "struct VESTArTypes.ElectionConfig",
"components": [
{
"name": "electionId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "seriesId",
"type": "bytes32",
Expand Down Expand Up @@ -542,16 +537,16 @@
"type": "function",
"name": "initialize",
"inputs": [
{
"name": "electionId_",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "config",
"type": "tuple",
"internalType": "struct VESTArTypes.ElectionConfig",
"components": [
{
"name": "electionId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "seriesId",
"type": "bytes32",
Expand Down
107 changes: 102 additions & 5 deletions abi/VESTArElectionFactory.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,50 @@
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "computeElectionId",
"inputs": [
{
"name": "organizer",
"type": "address",
"internalType": "address"
},
{
"name": "seriesId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "titleHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "startAt",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "endAt",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "organizerNonce",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "electionId",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "createElection",
Expand All @@ -39,11 +83,6 @@
"type": "tuple",
"internalType": "struct VESTArTypes.ElectionConfig",
"components": [
{
"name": "electionId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "seriesId",
"type": "bytes32",
Expand Down Expand Up @@ -239,6 +278,25 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "nextElectionNonce",
"inputs": [
{
"name": "organizer",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "organizerRegistry",
Expand Down Expand Up @@ -324,6 +382,45 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "previewNextElectionId",
"inputs": [
{
"name": "organizer",
"type": "address",
"internalType": "address"
},
{
"name": "seriesId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "titleHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "startAt",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "endAt",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "electionId",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "setKarmaRegistry",
Expand Down
10 changes: 5 additions & 5 deletions abi/status-testnet.addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"chainName": "Status Network Testnet",
"chainId": 1660990954,
"rpcUrl": "https://public.sepolia.rpc.status.network",
"OrganizerRegistry": "0x6b6F30c54F0a382328409941A8eB824D02EFCD8f",
"KarmaRegistry": "0x9880c7Ff7Be22A1B2e469E594157eE6C14604472",
"ElectionImplementation": "0x93ec16287D1da13b4af58f3F0B9D717cae8b4A8A",
"VESTArElectionFactory": "0xE9e5AE2892542fd736b5391f0a722C641DC1fEDe",
"MockUSDT": "0x3a91A1b0bF95eE4e3F4e2F3F2A386995D884ee1d"
"OrganizerRegistry": "0xebfABbb617a2bEA8dc2BD5C85ED6CAFdfBaa01F4",
"KarmaRegistry": "0x5e2609C80df13da46c1A9C65A5FF969518913609",
"ElectionImplementation": "0xE8b78126a720b8C7A35D0EC667faB1dAA53B2523",
"VESTArElectionFactory": "0xeEb174bE8A72aA4dDEd6A4f68b0055Ba0Ba446b3",
"MockUSDT": "0xF962A46C1d73440D58efb6b398Eeed6BBb0019Fd"
}
35 changes: 24 additions & 11 deletions src/interfaces/vestar/IVESTArElectionFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ interface IVESTArElectionFactory is IVESTArAdminControl {

// 어떤 karma registry를 참조하는지 조회
// karma registry : 유저의 Karma 기반 참여 자격을 판정하는 기준점
// Status의 Karma, KarmaTiers를 읽음
// 어떤 주소가 몇 티어인지 계산
// 최소 티어 이상인지 판정
// Status의 Karma, KarmaTiers를 읽음
// 어떤 주소가 몇 티어인지 계산
// 최소 티어 이상인지 판정
// 바로 Status 컨트랙트를 안 보는 이유 : 의존성을 한 레이어 감싸서 추상화
function karmaRegistry() external view returns (address);

Expand All @@ -52,21 +52,34 @@ interface IVESTArElectionFactory is IVESTArAdminControl {
// 같은 상위 이벤트/시리즈에 속한 election 개수
function totalElectionsInSeries(bytes32 seriesId) external view returns (uint256);

// organizer가 다음 create에서 사용할 nonce를 조회
function nextElectionNonce(address organizer) external view returns (uint256);

// 현재 nonce 기준으로 다음 electionId를 미리 계산
function previewNextElectionId(address organizer, bytes32 seriesId, bytes32 titleHash, uint64 startAt, uint64 endAt)
external
view
returns (bytes32 electionId);

// 특정 nonce를 넣어 electionId를 계산
function computeElectionId(
address organizer,
bytes32 seriesId,
bytes32 titleHash,
uint64 startAt,
uint64 endAt,
uint256 organizerNonce
) external view returns (bytes32 electionId);

// config struct 하나를 받아 새 election을 생성
function createElection(VESTArTypes.ElectionConfig calldata config) external returns (address electionAddress);

// electionId -> election address 매핑 조회
function getElection(bytes32 electionId) external view returns (address electionAddress);

// 같은 seriesId를 공유하는 electionId 목록 조회
function getSeriesElectionIds(bytes32 seriesId)
external
view
returns (bytes32[] memory electionIds);
function getSeriesElectionIds(bytes32 seriesId) external view returns (bytes32[] memory electionIds);

// 같은 seriesId를 공유하는 election address 목록 조회
function getSeriesElectionAddresses(bytes32 seriesId)
external
view
returns (address[] memory electionAddresses);
function getSeriesElectionAddresses(bytes32 seriesId) external view returns (address[] memory electionAddresses);
}
2 changes: 0 additions & 2 deletions src/libraries/vestar/VESTArTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity ^0.8.24;

// VESTAr 전역에서 같이 쓰는 enum / struct 타입들을 한 곳에 모아두는 파일
library VESTArTypes {

enum VisibilityMode {
OPEN,
PRIVATE
Expand Down Expand Up @@ -56,7 +55,6 @@ library VESTArTypes {

// ElectionConfig는 투표를 만들 때 필요한 핵심 설정 묶음
struct ElectionConfig {
bytes32 electionId;
// seriesId: "MAMA 2025" 같은 상위 이벤트/시리즈 식별자
// 예: female solo, male solo election이 같은 seriesId를 공유
bytes32 seriesId;
Expand Down
12 changes: 6 additions & 6 deletions src/vestar/election/VESTArElection.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ contract VESTArElection is VESTArElectionCore {
// 예시 : organizer가 createElection(config)를 호출하면 factory가 새 election을 만든 뒤
// initialize(...)에서 "이 투표는 누구 것인지, 어느 karma registry를 볼지, 어떤 토큰을 받을지"를 채움
function initialize(
bytes32 electionId_,
VESTArTypes.ElectionConfig calldata config,
address organizerAddress,
bool organizerVerifiedSnapshot_,
Expand All @@ -29,7 +30,7 @@ contract VESTArElection is VESTArElectionCore {
require(!initialized, "VESTAr: already initialized");
require(organizerAddress != address(0), "VESTAr: organizer is zero");
require(platformAdminAddress != address(0), "VESTAr: admin is zero");
require(config.electionId != bytes32(0), "VESTAr: electionId is zero");
require(electionId_ != bytes32(0), "VESTAr: electionId is zero");

// clone 배포 관련 코드 : clone은 constructor를 다시 타지 않으므로,
// 실제 election 인스턴스의 factory 주소와 owner를 initialize에서 직접 세팅해야 함
Expand All @@ -39,6 +40,7 @@ contract VESTArElection is VESTArElectionCore {

require(msg.sender == factory, "VESTAr: only factory");

_electionId = electionId_;
_config = config;
_organizer = organizerAddress;
_organizerVerifiedSnapshot = organizerVerifiedSnapshot_;
Expand All @@ -58,7 +60,7 @@ contract VESTArElection is VESTArElectionCore {

emit ElectionInitialized(
config.seriesId,
config.electionId,
electionId_,
organizerAddress,
config.visibilityMode,
organizerVerifiedSnapshot_,
Expand All @@ -85,9 +87,7 @@ contract VESTArElection is VESTArElectionCore {
_config.candidateManifestHash = newCandidateManifestHash;
_config.candidateManifestURI = newCandidateManifestURI;

emit ElectionMetadataUpdated(
_config.electionId, newTitleHash, newCandidateManifestHash, newCandidateManifestURI
);
emit ElectionMetadataUpdated(_electionId, newTitleHash, newCandidateManifestHash, newCandidateManifestURI);
}

// 후보 등록 관련 코드 : organizer/admin이 투표 시작 전에 후보 hash allowlist를 세팅
Expand All @@ -99,7 +99,7 @@ contract VESTArElection is VESTArElectionCore {

for (uint256 i = 0; i < candidateHashes.length; ++i) {
_allowedCandidateHash[candidateHashes[i]] = allowed;
emit CandidateAllowlistUpdated(_config.electionId, candidateHashes[i], allowed);
emit CandidateAllowlistUpdated(_electionId, candidateHashes[i], allowed);
}
}

Expand Down
11 changes: 3 additions & 8 deletions src/vestar/election/base/VESTArElectionStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ abstract contract VESTArElectionStorage {
uint256 internal constant UNLIMITED_PAID_COST_AMOUNT = 66_000;

VESTArTypes.ElectionConfig internal _config;
bytes32 internal _electionId;
VESTArTypes.ResultSummary internal _resultSummary;
VESTArTypes.CancellationSummary internal _cancellationSummary;
VESTArTypes.SettlementSummary internal _settlementSummary;
Expand Down Expand Up @@ -239,10 +240,7 @@ abstract contract VESTArElectionStorage {

// 관리자 권한 관련 코드 : platform admin 또는 organizer 둘 다 호출 가능하게 허용
function _requirePlatformAdminOrOrganizer() internal view {
require(
msg.sender == _platformAdmin || msg.sender == _organizer,
"VESTAr: only admin or organizer"
);
require(msg.sender == _platformAdmin || msg.sender == _organizer, "VESTAr: only admin or organizer");
}

// key reveal 권한 관련 코드 : platform admin은 항상 가능, 내부 팀 관리자는 별도 whitelist로 위임 가능
Expand All @@ -265,10 +263,7 @@ abstract contract VESTArElectionStorage {
require(candidateKeys.length > 0, "VESTAr: empty selection");

if (_config.allowMultipleChoice) {
require(
candidateKeys.length <= _config.maxSelectionsPerSubmission,
"VESTAr: too many selections"
);
require(candidateKeys.length <= _config.maxSelectionsPerSubmission, "VESTAr: too many selections");
} else {
require(candidateKeys.length == 1, "VESTAr: single choice only");
}
Expand Down
Loading
Loading